merge 64-bit fixes from Fernando Lucas Rodriguez <fernando_lr@terra.es>
[debian/gcpegg] / hw_pear.c
1 /* PROGRAM:     eggsh
2  * FILE:        $Header: /home/egg/src/RCS/hw_pear.c,v 1.3 1998/08/01 18:50:39 ghn Exp $
3  * PURPOSE:     PEAR (Bradish box/micro-REG) hardware interface
4  * AUTHOR:      Greg Nelson
5  * DATE:        98-04-12
6  *
7  * REVISED:     $Log: hw_pear.c,v $
8  * REVISED:     Revision 1.3  1998/08/01 18:50:39  ghn
9  * REVISED:     Added John's byte-order-independence changes and PSEUDO support.
10  * REVISED:
11  * REVISED:     Revision 1.2  1998/08/01 17:13:51  ghn
12  * REVISED:     Added John's Solaris support and DUMPREG option.
13  * REVISED:
14  * REVISED:     Revision 1.1  1998/07/21 11:37:41  ghn
15  * REVISED:     Initial revision
16  * REVISED:
17  * Copyright 1998 - Greg Nelson
18  * Redistributable under the terms of the GNU Public Licence (GPL)
19  */
20
21 /* Define this to dump samples from the REG which we actually use into
22    a file named dumpreg.dat.  This can be used to debug serial port
23    mode problems (for example, setting the character frame to 7 bits,
24    or telling it to ignore breaks, which will lose all zero bytes. */
25 /* #define DUMPREG */
26
27 #include <stdio.h>
28 #define __USE_BSD
29 #include <termios.h>
30 #undef __USE_BSD
31 #include <unistd.h>
32 #include <fcntl.h>
33 #define __USE_BSD
34 #include <errno.h>
35 #undef __USE_BSD
36
37 #include "global.h"
38 #include "genlib.h"
39 #include "hwapi.h"
40
41 #define MAXDEV  20
42
43 int32 oldbits[MAXDEV], bitsleft[MAXDEV];
44
45 #ifdef DUMPREG
46 static FILE *dumpfile;                /* REG dump file handle */
47 static unsigned char dumpbuf[1024];   /* REG dump buffer */
48 static int dumpptr = 0;               /* Pointer into dump buffer */
49 #endif
50
51 #ifdef PSEUDORANDOM_TEST
52 #include <stdlib.h>
53 static int pseudo = FALSE;            /* Nonzero if using pseudo-REG */
54 #endif
55
56 int32 OpenDev(DevOpts *opts) {
57   char ttydev[30];
58   speed_t baudcon;
59   struct termios tt;
60   int32 TTY_fd, res;
61
62 #ifdef DUMPREG
63   dumpfile = fopen("dumpreg.dat", "w");
64   setbuf(dumpfile, NULL);
65   dumpptr = 0;
66 #endif
67
68 #ifdef PSEUDORANDOM_TEST
69   if (opts->type == 0xFF) {
70     TTY_fd = 1;
71     oldbits[TTY_fd] = bitsleft[TTY_fd] = 0;
72     srandom(time(NULL));
73     pseudo = TRUE;
74     fprintf(stderr, "**** WARNING!  This egg has been configured to\n\
75                use a pseudorandom sequence generator to\n\
76                permit testing on machines not equipped\n\
77                with an REG.  Data from this egg should not\n\
78                be used for analysis.\n");
79     return TTY_fd;
80   }
81 #endif
82
83 #ifdef Solaris
84   /* Serial ports (at least built-in ones) have names of
85      /dev/term/a, /dev/term/b, etc.  Map the port numbers
86      from the RC file into this nomenclature, with "1"
87      designating /dev/term/a. */
88   sprintf(ttydev, "/dev/term/%c", 'a' + (opts->port - 1));
89 #else
90   sprintf(ttydev, "/dev/ttyS%d", opts->port);
91 #endif
92
93   switch(opts->baud) {
94   case 1200: baudcon = B1200; break;
95   case 2400: baudcon = B2400; break;
96   case 4800: baudcon = B4800; break;
97   case 9600: baudcon = B9600; break;
98   case 19200: baudcon = B19200; break;
99   case 38400: baudcon = B38400; break;
100 #ifndef Irix
101   case 115200: baudcon = B115200; break;
102 #endif
103   default:
104     printf("%s: Baud rate %ld not supported.\n", pgmname, opts->baud);
105     return -1;
106   }
107
108   fprintf(stderr, "Opening %s at %ld\n", ttydev, opts->baud);
109   if ((TTY_fd = open(ttydev, O_RDWR | O_NDELAY)) < 0) {
110     perror(pgmname);
111     return -1;
112   }
113
114   if (TTY_fd >= MAXDEV) {
115     fprintf(stderr, "%s: Too many devices open.\n", pgmname);
116     close(TTY_fd);
117     return -1;
118   }
119
120   res = tcgetattr(TTY_fd, &tt);
121 #ifdef Solaris
122   tt.c_iflag = 0;
123   tt.c_oflag = 0;
124   tt.c_cflag = baudcon | CS8 | CREAD | CLOCAL;
125   tt.c_lflag = 0;
126   tt.c_cc[VMIN] = 1;    /* This many chars satisfies reads */
127   tt.c_cc[VTIME] = 0;   /* or in this many tenths of seconds */
128 #else
129   res = cfsetospeed(&tt, baudcon); 
130   cfmakeraw(&tt);
131   tt.c_oflag &= (~(TABDLY | ONLCR));
132 #endif
133   res = tcsetattr(TTY_fd, TCSANOW, &tt);
134
135   oldbits[TTY_fd] = bitsleft[TTY_fd] = 0;
136   return TTY_fd;
137 }
138
139 #define SAMP_PERIOD     1000    /* msec */
140 #define MARGIN          .95     /* how much to headroom to allow in
141                                    speed measurement */
142
143 int32 EvalSpeed(int32 dd) {
144   struct timeval start, end;
145   int32 bitct, samp;
146
147   if (dd < 0) return -1;
148
149 #ifdef PSEUDORANDOM_TEST
150   if (pseudo) {
151     return 500;
152   }
153 #endif
154
155   gettimeofday(&start, NULL);
156   bitct = 0;
157   while (1) {
158     gettimeofday(&end, NULL);
159     if (deltams(&end, &start) >= SAMP_PERIOD) break;
160     samp = Sample(dd, 1);
161     bitct++;
162   }
163
164   return (int32)(bitct * MARGIN);
165 }
166
167 int32 Sample(int32 dd, uint16 bits) {
168   int32 bc, sum, n1;
169   uint8 c1;
170
171   if (dd < 0) return -1;
172
173   sum = bc = 0;
174   while (bc < bits) {
175     if (bitsleft[dd]) {
176       sum += (oldbits[dd] & 0x01);
177       oldbits[dd] >>= 1;
178       bitsleft[dd]--;
179       bc++;
180     } else {
181       do {
182 #ifdef PSEUDORANDOM_TEST
183         if (pseudo) {
184             n1 = 1;
185             c1 = (uint8) ((random() >> 5) & 0xFF);
186         } else
187 #endif
188         n1 = read(dd, &c1, 1);
189       } while (n1 == 0 || (n1 == -1 && errno == EAGAIN));
190       if (n1 == -1) {
191         /* Fatal error occurred, die now? */
192         return -1;
193       }
194 #ifdef DUMPREG
195       dumpbuf[dumpptr++] = c1;
196       if (dumpptr >= sizeof(dumpbuf)) {
197         fwrite(dumpbuf, sizeof(dumpbuf), 1, dumpfile);
198         dumpptr = 0;
199       }
200 #endif
201       oldbits[dd] = c1;
202       bitsleft[dd] = 8;
203     }
204   }
205
206   return sum;
207 }
208
209 int32 Discard(int32 dd) {
210   int32 disc, n1;
211   uint8 c1;
212   
213   if (dd < 0) return -1;
214
215   disc = bitsleft[dd];
216   bitsleft[dd] = 0;
217
218 #ifdef PSEUDORANDOM_TEST
219   if (pseudo) {
220     return 32;
221   }
222 #endif
223
224   do {
225     n1 = read(dd, &c1, 1);
226     if (n1 == 1) disc++;
227   } while (n1 == 1);
228
229   return disc;
230 }
231
232 int32 CloseDev(int32 dd) {
233   if (dd < 0) return -1;
234
235 #ifdef PSEUDORANDOM_TEST
236   if (!pseudo)
237 #endif
238   close(dd);
239   return 0;
240 }
241