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 * serpardv.c - Serial/Parallel Driver for Angel.
16b725ae77Skettenis */
17b725ae77Skettenis #include <stdio.h>
18b725ae77Skettenis #include <stdlib.h>
19b725ae77Skettenis #include <string.h>
20b725ae77Skettenis
21b725ae77Skettenis #include "crc.h"
22b725ae77Skettenis #include "devices.h"
23b725ae77Skettenis #include "buffers.h"
24b725ae77Skettenis #include "rxtx.h"
25b725ae77Skettenis #include "hostchan.h"
26b725ae77Skettenis #include "params.h"
27b725ae77Skettenis #include "logging.h"
28b725ae77Skettenis #include "hsys.h"
29b725ae77Skettenis
30b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
31b725ae77Skettenis # undef ERROR
32b725ae77Skettenis # undef IGNORE
33b725ae77Skettenis # include <windows.h>
34b725ae77Skettenis # include "angeldll.h"
35b725ae77Skettenis # include "comb_api.h"
36b725ae77Skettenis #else
37b725ae77Skettenis # ifdef __hpux
38b725ae77Skettenis # define _TERMIOS_INCLUDED
39b725ae77Skettenis # include <sys/termio.h>
40b725ae77Skettenis # undef _TERMIOS_INCLUDED
41b725ae77Skettenis # else
42b725ae77Skettenis # include <termios.h>
43b725ae77Skettenis # endif
44b725ae77Skettenis # include "unixcomm.h"
45b725ae77Skettenis #endif
46b725ae77Skettenis
47b725ae77Skettenis #ifndef UNUSED
48b725ae77Skettenis # define UNUSED(x) (x = x) /* Silence compiler warnings */
49b725ae77Skettenis #endif
50b725ae77Skettenis
51b725ae77Skettenis #define MAXREADSIZE 512
52b725ae77Skettenis #define MAXWRITESIZE 512
53b725ae77Skettenis
54b725ae77Skettenis #define SERPAR_FC_SET ((1 << serial_XON) | (1 << serial_XOFF))
55b725ae77Skettenis #define SERPAR_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) | \
56b725ae77Skettenis (1 << serial_ESC))
57b725ae77Skettenis #define SERPAR_ESC_SET (SERPAR_FC_SET | SERPAR_CTL_SET)
58b725ae77Skettenis
59b725ae77Skettenis static const struct re_config config = {
60b725ae77Skettenis serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
61b725ae77Skettenis SERPAR_FC_SET, /* set of flow-control characters */
62b725ae77Skettenis SERPAR_ESC_SET, /* set of characters to be escaped */
63b725ae77Skettenis NULL, /* serial_flow_control */
64b725ae77Skettenis NULL, /* what to do with FC chars */
65b725ae77Skettenis angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
66b725ae77Skettenis };
67b725ae77Skettenis
68b725ae77Skettenis static struct re_state rxstate;
69b725ae77Skettenis
70b725ae77Skettenis /*
71b725ae77Skettenis * structure used for manipulating transmit data
72b725ae77Skettenis */
73b725ae77Skettenis typedef struct TxState
74b725ae77Skettenis {
75b725ae77Skettenis struct te_state state;
76b725ae77Skettenis unsigned int index;
77b725ae77Skettenis unsigned char writebuf[MAXWRITESIZE];
78b725ae77Skettenis } TxState;
79b725ae77Skettenis
80b725ae77Skettenis /*
81b725ae77Skettenis * The set of parameter options supported by the device
82b725ae77Skettenis */
83b725ae77Skettenis static unsigned int baud_options[] =
84b725ae77Skettenis {
85b725ae77Skettenis #ifdef __hpux
86b725ae77Skettenis 115200, 57600,
87b725ae77Skettenis #endif
88b725ae77Skettenis 38400, 19200, 9600
89b725ae77Skettenis };
90b725ae77Skettenis
91b725ae77Skettenis static ParameterList param_list[] =
92b725ae77Skettenis {
93b725ae77Skettenis {
94b725ae77Skettenis AP_BAUD_RATE,
95b725ae77Skettenis sizeof(baud_options) / sizeof(unsigned int),
96b725ae77Skettenis baud_options
97b725ae77Skettenis }
98b725ae77Skettenis };
99b725ae77Skettenis
100b725ae77Skettenis static const ParameterOptions serpar_options =
101b725ae77Skettenis {
102b725ae77Skettenis sizeof(param_list) / sizeof(ParameterList),
103b725ae77Skettenis param_list
104b725ae77Skettenis };
105b725ae77Skettenis
106b725ae77Skettenis /*
107b725ae77Skettenis * The default parameter config for the device
108b725ae77Skettenis */
109b725ae77Skettenis static Parameter param_default[] =
110b725ae77Skettenis {
111b725ae77Skettenis { AP_BAUD_RATE, 9600 }
112b725ae77Skettenis };
113b725ae77Skettenis
114b725ae77Skettenis static const ParameterConfig serpar_defaults =
115b725ae77Skettenis {
116b725ae77Skettenis sizeof(param_default)/sizeof(Parameter),
117b725ae77Skettenis param_default
118b725ae77Skettenis };
119b725ae77Skettenis
120b725ae77Skettenis /*
121b725ae77Skettenis * The user-modified options for the device
122b725ae77Skettenis */
123b725ae77Skettenis static unsigned int user_baud_options[sizeof(baud_options) /
124b725ae77Skettenis sizeof(unsigned int)];
125b725ae77Skettenis
126b725ae77Skettenis static ParameterList param_user_list[] =
127b725ae77Skettenis {
128b725ae77Skettenis {
129b725ae77Skettenis AP_BAUD_RATE,
130b725ae77Skettenis sizeof(user_baud_options) / sizeof(unsigned),
131b725ae77Skettenis user_baud_options
132b725ae77Skettenis }
133b725ae77Skettenis };
134b725ae77Skettenis
135b725ae77Skettenis static ParameterOptions user_options =
136b725ae77Skettenis {
137b725ae77Skettenis sizeof(param_user_list) / sizeof(ParameterList),
138b725ae77Skettenis param_user_list
139b725ae77Skettenis };
140b725ae77Skettenis
141b725ae77Skettenis static bool user_options_set;
142b725ae77Skettenis
143b725ae77Skettenis /* forward declarations */
144b725ae77Skettenis static int serpar_reset(void);
145b725ae77Skettenis static int serpar_set_params(const ParameterConfig *config);
146b725ae77Skettenis static int SerparMatch(const char *name, const char *arg);
147b725ae77Skettenis
process_baud_rate(unsigned int target_baud_rate)148b725ae77Skettenis static void process_baud_rate(unsigned int target_baud_rate)
149b725ae77Skettenis {
150b725ae77Skettenis const ParameterList *full_list;
151b725ae77Skettenis ParameterList *user_list;
152b725ae77Skettenis
153b725ae77Skettenis /* create subset of full options */
154b725ae77Skettenis full_list = Angel_FindParamList(&serpar_options, AP_BAUD_RATE);
155b725ae77Skettenis user_list = Angel_FindParamList(&user_options, AP_BAUD_RATE);
156b725ae77Skettenis
157b725ae77Skettenis if (full_list != NULL && user_list != NULL)
158b725ae77Skettenis {
159b725ae77Skettenis unsigned int i, j;
160b725ae77Skettenis unsigned int def_baud = 0;
161b725ae77Skettenis
162b725ae77Skettenis /* find lower or equal to */
163b725ae77Skettenis for (i = 0; i < full_list->num_options; ++i)
164b725ae77Skettenis if (target_baud_rate >= full_list->option[i])
165b725ae77Skettenis {
166b725ae77Skettenis /* copy remaining */
167b725ae77Skettenis for (j = 0; j < (full_list->num_options - i); ++j)
168b725ae77Skettenis user_list->option[j] = full_list->option[i+j];
169b725ae77Skettenis user_list->num_options = j;
170b725ae77Skettenis
171b725ae77Skettenis /* check this is not the default */
172b725ae77Skettenis Angel_FindParam(AP_BAUD_RATE, &serpar_defaults, &def_baud);
173b725ae77Skettenis if ((j == 1) && (user_list->option[0] == def_baud))
174b725ae77Skettenis {
175b725ae77Skettenis #ifdef DEBUG
176b725ae77Skettenis printf("user selected default\n");
177b725ae77Skettenis #endif
178b725ae77Skettenis }
179b725ae77Skettenis else
180b725ae77Skettenis {
181b725ae77Skettenis user_options_set = TRUE;
182b725ae77Skettenis #ifdef DEBUG
183b725ae77Skettenis printf("user options are: ");
184b725ae77Skettenis for (j = 0; j < user_list->num_options; ++j)
185b725ae77Skettenis printf("%u ", user_list->option[j]);
186b725ae77Skettenis printf("\n");
187b725ae77Skettenis #endif
188b725ae77Skettenis }
189b725ae77Skettenis
190b725ae77Skettenis break; /* out of i loop */
191b725ae77Skettenis }
192b725ae77Skettenis
193b725ae77Skettenis #ifdef DEBUG
194b725ae77Skettenis if (i >= full_list->num_options)
195b725ae77Skettenis printf("couldn't match baud rate %u\n", target_baud_rate);
196b725ae77Skettenis #endif
197b725ae77Skettenis }
198b725ae77Skettenis #ifdef DEBUG
199b725ae77Skettenis else
200b725ae77Skettenis printf("failed to find lists\n");
201b725ae77Skettenis #endif
202b725ae77Skettenis }
203b725ae77Skettenis
SerparOpen(const char * name,const char * arg)204b725ae77Skettenis static int SerparOpen(const char *name, const char *arg)
205b725ae77Skettenis {
206b725ae77Skettenis char *sername = NULL;
207b725ae77Skettenis char *parname = NULL;
208b725ae77Skettenis
209b725ae77Skettenis #ifdef DEBUG
210b725ae77Skettenis printf("SerparOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
211b725ae77Skettenis #endif
212b725ae77Skettenis
213b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
214b725ae77Skettenis if (IsOpenSerial() || IsOpenParallel()) return -1;
215b725ae77Skettenis #else
216b725ae77Skettenis if (Unix_IsSerialInUse() || Unix_IsParallelInUse()) return -1;
217b725ae77Skettenis #endif
218b725ae77Skettenis
219b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
220b725ae77Skettenis if (SerparMatch(name, arg) == -1)
221b725ae77Skettenis return -1;
222b725ae77Skettenis #else
223b725ae77Skettenis Unix_IsValidParallelDevice(name,&sername,&parname);
224b725ae77Skettenis # ifdef DEBUG
225b725ae77Skettenis printf("translated %s to serial %s and parallel %s\n",
226b725ae77Skettenis name==0 ? "NULL" : name,
227b725ae77Skettenis sername==0 ? "NULL" : sername,
228b725ae77Skettenis parname==0 ? "NULL" : parname);
229b725ae77Skettenis # endif
230b725ae77Skettenis if (sername==NULL || parname==NULL) return -1;
231b725ae77Skettenis #endif
232b725ae77Skettenis
233b725ae77Skettenis user_options_set = FALSE;
234b725ae77Skettenis
235b725ae77Skettenis /* interpret and store the arguments */
236b725ae77Skettenis if (arg != NULL)
237b725ae77Skettenis {
238b725ae77Skettenis unsigned int target_baud_rate;
239b725ae77Skettenis
240b725ae77Skettenis target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
241b725ae77Skettenis
242b725ae77Skettenis if (target_baud_rate > 0)
243b725ae77Skettenis {
244b725ae77Skettenis #ifdef DEBUG
245b725ae77Skettenis printf("user selected baud rate %u\n", target_baud_rate);
246b725ae77Skettenis #endif
247b725ae77Skettenis process_baud_rate(target_baud_rate);
248b725ae77Skettenis }
249b725ae77Skettenis #ifdef DEBUG
250b725ae77Skettenis else
251b725ae77Skettenis printf("could not understand baud rate %s\n", arg);
252b725ae77Skettenis #endif
253b725ae77Skettenis }
254b725ae77Skettenis
255b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
256b725ae77Skettenis {
257b725ae77Skettenis /*
258b725ae77Skettenis * The serial port number is in name[0] followed by
259b725ae77Skettenis * the parallel port number in name[1]
260b725ae77Skettenis */
261b725ae77Skettenis
262b725ae77Skettenis int sport = name[0] - '0';
263b725ae77Skettenis int pport = name[1] - '0';
264b725ae77Skettenis
265b725ae77Skettenis if (OpenParallel(pport) != COM_OK)
266b725ae77Skettenis return -1;
267b725ae77Skettenis
268b725ae77Skettenis if (OpenSerial(sport, FALSE) != COM_OK)
269b725ae77Skettenis {
270b725ae77Skettenis CloseParallel();
271b725ae77Skettenis return -1;
272b725ae77Skettenis }
273b725ae77Skettenis }
274b725ae77Skettenis #else
275b725ae77Skettenis Unix_OpenParallel(parname);
276b725ae77Skettenis Unix_OpenSerial(sername);
277b725ae77Skettenis #endif
278b725ae77Skettenis
279b725ae77Skettenis serpar_reset();
280b725ae77Skettenis
281b725ae77Skettenis #if defined(__unix) || defined(__CYGWIN__)
282b725ae77Skettenis Unix_ioctlNonBlocking();
283b725ae77Skettenis #endif
284b725ae77Skettenis
285b725ae77Skettenis Angel_RxEngineInit(&config, &rxstate);
286b725ae77Skettenis
287b725ae77Skettenis return 0;
288b725ae77Skettenis }
289b725ae77Skettenis
290b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
SerparMatch(const char * name,const char * arg)291b725ae77Skettenis static int SerparMatch(const char *name, const char *arg)
292b725ae77Skettenis {
293b725ae77Skettenis char sername[2];
294b725ae77Skettenis char parname[2];
295b725ae77Skettenis
296b725ae77Skettenis UNUSED(arg);
297b725ae77Skettenis
298b725ae77Skettenis sername[0] = name[0];
299b725ae77Skettenis parname[0] = name[1];
300b725ae77Skettenis sername[1] = parname[1] = 0;
301b725ae77Skettenis
302b725ae77Skettenis if (IsValidDevice(sername) == COM_DEVICENOTVALID ||
303b725ae77Skettenis IsValidDevice(parname) == COM_DEVICENOTVALID)
304b725ae77Skettenis return -1;
305b725ae77Skettenis else
306b725ae77Skettenis return 0;
307b725ae77Skettenis }
308b725ae77Skettenis #else
SerparMatch(const char * portstring,const char * arg)309b725ae77Skettenis static int SerparMatch(const char *portstring, const char *arg)
310b725ae77Skettenis {
311b725ae77Skettenis char *sername=NULL, *parname=NULL;
312b725ae77Skettenis UNUSED(arg);
313b725ae77Skettenis
314b725ae77Skettenis Unix_IsValidParallelDevice(portstring,&sername,&parname);
315b725ae77Skettenis
316b725ae77Skettenis /* Match failed if either sername or parname are still NULL */
317b725ae77Skettenis if (sername==NULL || parname==NULL) return -1;
318b725ae77Skettenis return 0;
319b725ae77Skettenis }
320b725ae77Skettenis #endif
321b725ae77Skettenis
SerparClose(void)322b725ae77Skettenis static void SerparClose(void)
323b725ae77Skettenis {
324b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
325b725ae77Skettenis CloseParallel();
326b725ae77Skettenis CloseSerial();
327b725ae77Skettenis #else
328b725ae77Skettenis Unix_CloseParallel();
329b725ae77Skettenis Unix_CloseSerial();
330b725ae77Skettenis #endif
331b725ae77Skettenis }
332b725ae77Skettenis
SerparRead(DriverCall * dc,bool block)333b725ae77Skettenis static int SerparRead(DriverCall *dc, bool block)
334b725ae77Skettenis {
335b725ae77Skettenis static unsigned char readbuf[MAXREADSIZE];
336b725ae77Skettenis static int rbindex = 0;
337b725ae77Skettenis
338b725ae77Skettenis int nread;
339b725ae77Skettenis int read_errno;
340b725ae77Skettenis int c = 0;
341b725ae77Skettenis re_status restatus;
342b725ae77Skettenis int ret_code = -1; /* assume bad packet or error */
343b725ae77Skettenis
344b725ae77Skettenis /*
345b725ae77Skettenis * we must not overflow buffer, and must start after
346b725ae77Skettenis * the existing data
347b725ae77Skettenis */
348b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
349b725ae77Skettenis {
350b725ae77Skettenis BOOL dummy = FALSE;
351b725ae77Skettenis nread = BytesInRXBufferSerial();
352b725ae77Skettenis
353b725ae77Skettenis if (nread > MAXREADSIZE - rbindex)
354b725ae77Skettenis nread = MAXREADSIZE - rbindex;
355b725ae77Skettenis read_errno = ReadSerial(readbuf+rbindex, nread, &dummy);
356b725ae77Skettenis if (pfnProgressCallback != NULL && read_errno == COM_OK)
357b725ae77Skettenis {
358b725ae77Skettenis progressInfo.nRead += nread;
359b725ae77Skettenis (*pfnProgressCallback)(&progressInfo);
360b725ae77Skettenis }
361b725ae77Skettenis }
362b725ae77Skettenis #else
363b725ae77Skettenis nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
364b725ae77Skettenis read_errno = errno;
365b725ae77Skettenis #endif
366b725ae77Skettenis
367b725ae77Skettenis if ((nread > 0) || (rbindex > 0))
368b725ae77Skettenis {
369b725ae77Skettenis #ifdef DO_TRACE
370b725ae77Skettenis printf("[%d@%d] ", nread, rbindex);
371b725ae77Skettenis #endif
372b725ae77Skettenis
373b725ae77Skettenis if (nread > 0)
374b725ae77Skettenis rbindex = rbindex + nread;
375b725ae77Skettenis
376b725ae77Skettenis do
377b725ae77Skettenis {
378b725ae77Skettenis restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
379b725ae77Skettenis
380b725ae77Skettenis #ifdef DO_TRACE
381b725ae77Skettenis printf("<%02X ",readbuf[c]);
382b725ae77Skettenis #endif
383b725ae77Skettenis c++;
384b725ae77Skettenis } while (c < rbindex &&
385b725ae77Skettenis ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
386b725ae77Skettenis
387b725ae77Skettenis #ifdef DO_TRACE
388b725ae77Skettenis printf("\n");
389b725ae77Skettenis #endif
390b725ae77Skettenis
391b725ae77Skettenis switch(restatus)
392b725ae77Skettenis {
393b725ae77Skettenis case RS_GOOD_PKT:
394b725ae77Skettenis ret_code = 1;
395b725ae77Skettenis /* fall through to: */
396b725ae77Skettenis
397b725ae77Skettenis case RS_BAD_PKT:
398b725ae77Skettenis /*
399b725ae77Skettenis * We now need to shuffle any left over data down to the
400b725ae77Skettenis * beginning of our private buffer ready to be used
401b725ae77Skettenis *for the next packet
402b725ae77Skettenis */
403b725ae77Skettenis #ifdef DO_TRACE
404b725ae77Skettenis printf("SerparRead() processed %d, moving down %d\n",
405b725ae77Skettenis c, rbindex - c);
406b725ae77Skettenis #endif
407b725ae77Skettenis
408b725ae77Skettenis if (c != rbindex)
409b725ae77Skettenis memmove((char *) readbuf, (char *) (readbuf + c), rbindex - c);
410b725ae77Skettenis
411b725ae77Skettenis rbindex -= c;
412b725ae77Skettenis
413b725ae77Skettenis break;
414b725ae77Skettenis
415b725ae77Skettenis case RS_IN_PKT:
416b725ae77Skettenis case RS_WAIT_PKT:
417b725ae77Skettenis rbindex = 0; /* will have processed all we had */
418b725ae77Skettenis ret_code = 0;
419b725ae77Skettenis break;
420b725ae77Skettenis
421b725ae77Skettenis default:
422b725ae77Skettenis #ifdef DEBUG
423b725ae77Skettenis printf("Bad re_status in SerparRead()\n");
424b725ae77Skettenis #endif
425b725ae77Skettenis break;
426b725ae77Skettenis }
427b725ae77Skettenis }
428b725ae77Skettenis else if (nread == 0)
429b725ae77Skettenis /* nothing to read */
430b725ae77Skettenis ret_code = 0;
431b725ae77Skettenis else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
432b725ae77Skettenis ret_code = 0;
433b725ae77Skettenis
434b725ae77Skettenis #ifdef DEBUG
435b725ae77Skettenis if ((nread < 0) && (read_errno != ERRNO_FOR_BLOCKED_IO))
436b725ae77Skettenis perror("read() error in SerparRead()");
437b725ae77Skettenis #endif
438b725ae77Skettenis
439b725ae77Skettenis return ret_code;
440b725ae77Skettenis }
441b725ae77Skettenis
442b725ae77Skettenis /*
443b725ae77Skettenis * Function: send_packet
444b725ae77Skettenis * Purpose: Send a stream of bytes to Angel through the parallel port
445b725ae77Skettenis *
446b725ae77Skettenis * Algorithm: We need to present the data in a form that all boards can
447b725ae77Skettenis * swallow. With the PID board, this is a problem: for reasons
448b725ae77Skettenis * described in the driver (angel/pid/st16c552.c), data are
449b725ae77Skettenis * sent a nybble at a time on D0-D2 and D4; D3 is wired to ACK,
450b725ae77Skettenis * which generates an interrupt when it goes low. This routine
451b725ae77Skettenis * fills in an array of nybbles, with ACK clear in all but the
452b725ae77Skettenis * last one. If, for whatever reason, the write fails, then
453b725ae77Skettenis * ACK is forced high (thereby enabling the next write a chance
454b725ae77Skettenis * to be noticed when the falling edge of ACK generates an
455b725ae77Skettenis * interrupt (hopefully).
456b725ae77Skettenis *
457b725ae77Skettenis * Params:
458b725ae77Skettenis * Input: txstate Contains the packet to be sent
459b725ae77Skettenis *
460b725ae77Skettenis * Returns: Number of *complete* bytes written
461b725ae77Skettenis */
462b725ae77Skettenis
SerparWrite(DriverCall * dc)463b725ae77Skettenis static int SerparWrite(DriverCall *dc)
464b725ae77Skettenis {
465b725ae77Skettenis te_status status;
466b725ae77Skettenis int nwritten = 0;
467b725ae77Skettenis static TxState txstate;
468b725ae77Skettenis
469b725ae77Skettenis /*
470b725ae77Skettenis * is this a new packet?
471b725ae77Skettenis */
472b725ae77Skettenis if (dc->dc_context == NULL)
473b725ae77Skettenis {
474b725ae77Skettenis /*
475b725ae77Skettenis * yes - initialise TxEngine
476b725ae77Skettenis */
477b725ae77Skettenis Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state);
478b725ae77Skettenis
479b725ae77Skettenis txstate.index = 0;
480b725ae77Skettenis dc->dc_context = &txstate;
481b725ae77Skettenis }
482b725ae77Skettenis
483b725ae77Skettenis /*
484b725ae77Skettenis * fill the buffer using the Tx Engine
485b725ae77Skettenis */
486b725ae77Skettenis do
487b725ae77Skettenis {
488b725ae77Skettenis status = Angel_TxEngine(&dc->dc_packet, &txstate.state,
489b725ae77Skettenis &txstate.writebuf[txstate.index]);
490b725ae77Skettenis if (status != TS_IDLE) txstate.index++;
491b725ae77Skettenis
492b725ae77Skettenis } while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE);
493b725ae77Skettenis
494b725ae77Skettenis #ifdef DO_TRACE
495b725ae77Skettenis {
496b725ae77Skettenis unsigned int i = 0;
497b725ae77Skettenis
498b725ae77Skettenis while (i < txstate.index)
499b725ae77Skettenis {
500b725ae77Skettenis printf(">%02X ", txstate.writebuf[i]);
501b725ae77Skettenis
502b725ae77Skettenis if (!(++i % 16))
503b725ae77Skettenis putc('\n', stdout);
504b725ae77Skettenis }
505b725ae77Skettenis
506b725ae77Skettenis if (i % 16)
507b725ae77Skettenis putc('\n', stdout);
508b725ae77Skettenis }
509b725ae77Skettenis #endif
510b725ae77Skettenis
511b725ae77Skettenis /*
512b725ae77Skettenis * the data are ready, all we need now is to send them out
513b725ae77Skettenis * in a form that Angel can swallow.
514b725ae77Skettenis */
515b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
516b725ae77Skettenis if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK)
517b725ae77Skettenis {
518b725ae77Skettenis nwritten = txstate.index;
519b725ae77Skettenis if (pfnProgressCallback != NULL)
520b725ae77Skettenis {
521b725ae77Skettenis progressInfo.nWritten += nwritten;
522b725ae77Skettenis (*pfnProgressCallback)(&progressInfo);
523b725ae77Skettenis }
524b725ae77Skettenis }
525b725ae77Skettenis else
526b725ae77Skettenis {
527b725ae77Skettenis MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
528b725ae77Skettenis return -1; /* SJ - This really needs to return a value, which is picked up in */
529b725ae77Skettenis /* DevSW_Read as meaning stop debugger but don't kill. */
530b725ae77Skettenis }
531b725ae77Skettenis #else
532b725ae77Skettenis nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index);
533b725ae77Skettenis #endif
534b725ae77Skettenis
535b725ae77Skettenis if (nwritten < 0) nwritten = 0;
536b725ae77Skettenis
537b725ae77Skettenis #ifdef DO_TRACE
538b725ae77Skettenis printf("SerparWrite: wrote %d out of %d bytes\n",
539b725ae77Skettenis nwritten, txstate.index);
540b725ae77Skettenis #endif
541b725ae77Skettenis
542b725ae77Skettenis /*
543b725ae77Skettenis * has the whole packet gone?
544b725ae77Skettenis */
545b725ae77Skettenis if (nwritten == (int)txstate.index &&
546b725ae77Skettenis (status == TS_DONE_PKT || status == TS_IDLE))
547b725ae77Skettenis /*
548b725ae77Skettenis * yes it has
549b725ae77Skettenis */
550b725ae77Skettenis return 1;
551b725ae77Skettenis else
552b725ae77Skettenis {
553b725ae77Skettenis /*
554b725ae77Skettenis * if some data are left, shuffle them
555b725ae77Skettenis * to the start of the buffer
556b725ae77Skettenis */
557b725ae77Skettenis if (nwritten != (int)txstate.index && nwritten != 0)
558b725ae77Skettenis {
559b725ae77Skettenis txstate.index -= nwritten;
560b725ae77Skettenis (void)memmove((char *) txstate.writebuf,
561b725ae77Skettenis (char *) (txstate.writebuf + nwritten),
562b725ae77Skettenis txstate.index);
563b725ae77Skettenis }
564b725ae77Skettenis else if (nwritten == (int)txstate.index)
565b725ae77Skettenis txstate.index = 0;
566b725ae77Skettenis
567b725ae77Skettenis return 0;
568b725ae77Skettenis }
569b725ae77Skettenis }
570b725ae77Skettenis
serpar_reset(void)571b725ae77Skettenis static int serpar_reset(void)
572b725ae77Skettenis {
573b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
574b725ae77Skettenis FlushParallel();
575b725ae77Skettenis FlushSerial();
576b725ae77Skettenis #else
577b725ae77Skettenis Unix_ResetParallel();
578b725ae77Skettenis Unix_ResetSerial();
579b725ae77Skettenis #endif
580b725ae77Skettenis
581b725ae77Skettenis return serpar_set_params(&serpar_defaults);
582b725ae77Skettenis }
583b725ae77Skettenis
find_baud_rate(unsigned int * speed)584b725ae77Skettenis static int find_baud_rate(unsigned int *speed)
585b725ae77Skettenis {
586b725ae77Skettenis static struct
587b725ae77Skettenis {
588b725ae77Skettenis unsigned int baud;
589b725ae77Skettenis int termiosValue;
590b725ae77Skettenis } possibleBaudRates[] =
591b725ae77Skettenis {
592b725ae77Skettenis #if defined(__hpux)
593b725ae77Skettenis {115200, _B115200}, {57600, _B57600},
594b725ae77Skettenis #endif
595b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
596b725ae77Skettenis {38400, CBR_38400}, {19200, CBR_19200}, {9600, CBR_9600}, {0, 0}
597b725ae77Skettenis #else
598b725ae77Skettenis {38400, B38400}, {19200, B19200}, {9600, B9600}, {0, 0}
599b725ae77Skettenis #endif
600b725ae77Skettenis };
601b725ae77Skettenis unsigned int i;
602b725ae77Skettenis
603b725ae77Skettenis /* look for lower or matching -- will always terminate at 0 end marker */
604b725ae77Skettenis for (i = 0; possibleBaudRates[i].baud > *speed; ++i)
605b725ae77Skettenis /* do nothing */
606b725ae77Skettenis ;
607b725ae77Skettenis
608b725ae77Skettenis if (possibleBaudRates[i].baud > 0)
609b725ae77Skettenis *speed = possibleBaudRates[i].baud;
610b725ae77Skettenis
611b725ae77Skettenis return possibleBaudRates[i].termiosValue;
612b725ae77Skettenis }
613b725ae77Skettenis
serpar_set_params(const ParameterConfig * config)614b725ae77Skettenis static int serpar_set_params(const ParameterConfig *config)
615b725ae77Skettenis {
616b725ae77Skettenis unsigned int speed;
617b725ae77Skettenis int termios_value;
618b725ae77Skettenis
619b725ae77Skettenis #ifdef DEBUG
620b725ae77Skettenis printf("serpar_set_params\n");
621b725ae77Skettenis #endif
622b725ae77Skettenis
623b725ae77Skettenis if (!Angel_FindParam(AP_BAUD_RATE, config, &speed))
624b725ae77Skettenis {
625b725ae77Skettenis #ifdef DEBUG
626b725ae77Skettenis printf("speed not found in config\n");
627b725ae77Skettenis #endif
628b725ae77Skettenis return DE_OKAY;
629b725ae77Skettenis }
630b725ae77Skettenis
631b725ae77Skettenis termios_value = find_baud_rate(&speed);
632b725ae77Skettenis if (termios_value == 0)
633b725ae77Skettenis {
634b725ae77Skettenis #ifdef DEBUG
635b725ae77Skettenis printf("speed not valid: %u\n", speed);
636b725ae77Skettenis #endif
637b725ae77Skettenis return DE_OKAY;
638b725ae77Skettenis }
639b725ae77Skettenis
640b725ae77Skettenis #ifdef DEBUG
641b725ae77Skettenis printf("setting speed to %u\n", speed);
642b725ae77Skettenis #endif
643b725ae77Skettenis
644b725ae77Skettenis #ifdef COMPILING_ON_WINDOWS
645b725ae77Skettenis SetBaudRate((WORD)termios_value);
646b725ae77Skettenis #else
647b725ae77Skettenis Unix_SetSerialBaudRate(termios_value);
648b725ae77Skettenis #endif
649b725ae77Skettenis
650b725ae77Skettenis return DE_OKAY;
651b725ae77Skettenis }
652b725ae77Skettenis
653b725ae77Skettenis
serpar_get_user_params(ParameterOptions ** p_options)654b725ae77Skettenis static int serpar_get_user_params(ParameterOptions **p_options)
655b725ae77Skettenis {
656b725ae77Skettenis #ifdef DEBUG
657b725ae77Skettenis printf("serpar_get_user_params\n");
658b725ae77Skettenis #endif
659b725ae77Skettenis
660b725ae77Skettenis if (user_options_set)
661b725ae77Skettenis {
662b725ae77Skettenis *p_options = &user_options;
663b725ae77Skettenis }
664b725ae77Skettenis else
665b725ae77Skettenis {
666b725ae77Skettenis *p_options = NULL;
667b725ae77Skettenis }
668b725ae77Skettenis
669b725ae77Skettenis return DE_OKAY;
670b725ae77Skettenis }
671b725ae77Skettenis
672b725ae77Skettenis
serial_get_default_params(const ParameterConfig ** p_config)673b725ae77Skettenis static int serial_get_default_params( const ParameterConfig **p_config )
674b725ae77Skettenis {
675b725ae77Skettenis #ifdef DEBUG
676b725ae77Skettenis printf( "serial_get_default_params\n" );
677b725ae77Skettenis #endif
678b725ae77Skettenis
679b725ae77Skettenis *p_config = &serpar_defaults;
680b725ae77Skettenis return DE_OKAY;
681b725ae77Skettenis }
682b725ae77Skettenis
683b725ae77Skettenis
SerparIoctl(const int opcode,void * args)684b725ae77Skettenis static int SerparIoctl(const int opcode, void *args)
685b725ae77Skettenis {
686b725ae77Skettenis int ret_code;
687b725ae77Skettenis
688b725ae77Skettenis #ifdef DEBUG
689b725ae77Skettenis printf("SerparIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
690b725ae77Skettenis #endif
691b725ae77Skettenis
692b725ae77Skettenis switch (opcode)
693b725ae77Skettenis {
694b725ae77Skettenis case DC_RESET:
695b725ae77Skettenis ret_code = serpar_reset();
696b725ae77Skettenis break;
697b725ae77Skettenis
698b725ae77Skettenis case DC_SET_PARAMS:
699b725ae77Skettenis ret_code = serpar_set_params((const ParameterConfig *)args);
700b725ae77Skettenis break;
701b725ae77Skettenis
702b725ae77Skettenis case DC_GET_USER_PARAMS:
703b725ae77Skettenis ret_code = serpar_get_user_params((ParameterOptions **)args);
704b725ae77Skettenis break;
705b725ae77Skettenis
706b725ae77Skettenis case DC_GET_DEFAULT_PARAMS:
707b725ae77Skettenis ret_code =
708b725ae77Skettenis serial_get_default_params((const ParameterConfig **)args);
709b725ae77Skettenis break;
710b725ae77Skettenis
711b725ae77Skettenis default:
712b725ae77Skettenis ret_code = DE_BAD_OP;
713b725ae77Skettenis break;
714b725ae77Skettenis }
715b725ae77Skettenis
716b725ae77Skettenis return ret_code;
717b725ae77Skettenis }
718b725ae77Skettenis
719b725ae77Skettenis DeviceDescr angel_SerparDevice =
720b725ae77Skettenis {
721b725ae77Skettenis "SERPAR",
722b725ae77Skettenis SerparOpen,
723b725ae77Skettenis SerparMatch,
724b725ae77Skettenis SerparClose,
725b725ae77Skettenis SerparRead,
726b725ae77Skettenis SerparWrite,
727b725ae77Skettenis SerparIoctl
728b725ae77Skettenis };
729b725ae77Skettenis
730b725ae77Skettenis /* EOF serpardr.c */
731