xref: /openbsd-src/gnu/usr.bin/binutils/gdb/rdi-share/serpardr.c (revision 63addd46c1e40ca0f49488ddcdc4ab598023b0c1)
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