]>
Commit | Line | Data |
---|---|---|
726f69e2 KZ |
1 | /* cytune.c -- Tune Cyclades driver |
2 | * | |
3 | * Copyright 1995 Nick Simicich (njs@scifi.emi.net) | |
4 | * | |
5 | * Modifications by Rik Faith (faith@cs.unc.edu) | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. All advertising materials mentioning features or use of this software | |
16 | * must display the following acknowledgement: | |
17 | * This product includes software developed by the Nick Simicich | |
18 | * 4. Neither the name of the Nick Simicich nor the names of its contributors | |
19 | * may be used to endorse or promote products derived from this software | |
20 | * without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND | |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | |
33 | * | |
34 | */ | |
35 | ||
36 | #include <stdio.h> | |
37 | #include <stdlib.h> | |
726f69e2 KZ |
38 | #include <sys/types.h> |
39 | #include <sys/time.h> | |
40 | #include <sys/ioctl.h> | |
41 | #include <unistd.h> | |
fd6b7a7f | 42 | #include <string.h> |
726f69e2 KZ |
43 | #include <fcntl.h> |
44 | #include <errno.h> | |
45 | #include <linux/tty.h> | |
46 | #include <termios.h> | |
2b6fc908 KZ |
47 | #if 0 |
48 | #include <linux/tqueue.h> /* required for old kernels */ | |
49 | /* compilation errors on other kernels */ | |
50 | #endif | |
726f69e2 KZ |
51 | #include <linux/cyclades.h> |
52 | #include <signal.h> | |
53 | ||
54 | #if 0 | |
55 | #ifndef XMIT | |
56 | # include <linux/version.h> | |
57 | # if LINUX_VERSION_CODE > 66056 | |
58 | # define XMIT | |
59 | # endif | |
60 | #endif | |
61 | #endif | |
62 | /* Until it gets put in the kernel, | |
63 | toggle by hand. */ | |
64 | #undef XMIT | |
65 | ||
66 | struct cyclades_control { | |
67 | struct cyclades_monitor c; | |
68 | int cfile; | |
69 | int maxmax; | |
70 | double maxtran; | |
71 | double maxxmit; | |
72 | unsigned long threshold_value; | |
73 | unsigned long timeout_value; | |
74 | }; | |
75 | struct cyclades_control *cmon; | |
76 | int cmon_index; | |
77 | ||
78 | #define mvtime(tvpto, tvpfrom) (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec) | |
79 | ||
80 | ||
81 | inline double dtime(struct timeval * tvpnew, struct timeval * tvpold) { | |
82 | double diff; | |
83 | diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec; | |
84 | diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec)/1000000; | |
85 | return diff; | |
86 | } | |
87 | ||
88 | static int global_argc, global_optind; | |
89 | static char ***global_argv; | |
90 | ||
91 | void summary(int signal) { | |
92 | struct cyclades_control *cc; | |
93 | ||
94 | int argc, optind; | |
95 | char **argv; | |
96 | ||
97 | int i,j; | |
98 | ||
99 | argc = global_argc; | |
100 | argv = *global_argv; | |
101 | optind = global_optind; | |
102 | ||
103 | if (signal > 0) { | |
104 | for(i = optind; i < argc; i ++) { | |
105 | j = i - optind; | |
106 | cc = &cmon[cmon_index]; | |
107 | fprintf(stderr, "File %s, For threshold value %lu, Maximum characters " | |
108 | "in fifo were %d,\nand the maximum transfer rate in " | |
109 | "characters/second was %f\n", | |
110 | argv[i], | |
111 | cc->threshold_value, | |
112 | cc->maxmax, | |
113 | cc->maxtran); | |
114 | } | |
115 | ||
116 | exit(0); | |
117 | } | |
118 | cc = &cmon[cmon_index]; | |
119 | if (cc->threshold_value > 0 && signal != -1) { | |
120 | fprintf(stderr, "File %s, For threshold value %lu and timrout value %lu," | |
121 | " Maximum characters " | |
122 | "in fifo were %d,\nand the maximum transfer rate in " | |
123 | "characters/second was %f\n", | |
124 | argv[cmon_index+optind], | |
125 | cc->threshold_value, | |
126 | cc->timeout_value, | |
127 | cc->maxmax, | |
128 | cc->maxtran); | |
129 | } | |
130 | cc->maxmax = 0; | |
131 | cc->maxtran = 0.0; | |
132 | cc->threshold_value = 0; | |
133 | cc->timeout_value = 0; | |
134 | } | |
135 | ||
136 | static int query = 0; | |
137 | static int interval = 1; | |
138 | ||
139 | static int set = 0; | |
140 | static int set_val = -1; | |
141 | static int get = 0; | |
142 | ||
143 | static int set_def = 0; | |
144 | static int set_def_val = -1; | |
145 | static int get_def = 0; | |
146 | ||
147 | static int set_time = 0; | |
148 | static int set_time_val = -1; | |
149 | ||
150 | static int set_def_time = 0; | |
151 | static int set_def_time_val = -1; | |
152 | ||
153 | ||
154 | int main(int argc, char *argv[]) { | |
155 | ||
156 | struct timeval lasttime, thistime; | |
fd6b7a7f | 157 | struct timezone tz = {0,0}; |
726f69e2 KZ |
158 | double diff; |
159 | int errflg = 0; | |
160 | int file; | |
161 | int numfiles; | |
162 | struct cyclades_monitor cywork; | |
163 | ||
164 | int i; | |
165 | extern char *optarg; | |
166 | extern int optind; | |
167 | unsigned long threshold_value; | |
168 | unsigned long timeout_value; | |
169 | double xfer_rate; | |
170 | #ifdef XMIT | |
171 | double xmit_rate; | |
172 | #endif | |
173 | ||
174 | global_argc = argc; /* For signal routine. */ | |
175 | global_argv = &argv; /* For signal routine. */ | |
176 | ||
177 | while (EOF != (i = getopt(argc, argv, | |
178 | "qs:S:t:T:gGi:"))) { | |
179 | switch (i) { | |
180 | case 'q': | |
181 | query = 1; | |
182 | break; | |
183 | case 'i': | |
184 | interval = atoi(optarg); | |
185 | if(interval <= 0) { | |
186 | fprintf(stderr, "Invalid interval value: %s\n",optarg); | |
187 | errflg ++; | |
188 | } | |
189 | break; | |
190 | case 's': | |
191 | ++set; | |
192 | set_val = atoi(optarg); | |
193 | if(set_val <= 0 || set_val > 12) { | |
194 | fprintf(stderr, "Invalid set value: %s\n",optarg); | |
195 | errflg ++; | |
196 | } | |
197 | break; | |
198 | case 'S': | |
199 | ++set_def; | |
200 | set_def_val = atoi(optarg); | |
201 | if(set_def_val < 0 || set_def_val > 12) { | |
202 | fprintf(stderr, "Invalid default value: %s\n",optarg); | |
203 | errflg ++; | |
204 | } | |
205 | break; | |
206 | case 't': | |
207 | ++set_time; | |
208 | set_time_val = atoi(optarg); | |
209 | if(set_time_val <= 0 || set_time_val > 255) { | |
210 | fprintf(stderr, "Invalid set time value: %s\n",optarg); | |
211 | errflg ++; | |
212 | } | |
213 | break; | |
214 | case 'T': | |
215 | ++set_def_time; | |
216 | set_def_time_val = atoi(optarg); | |
217 | if(set_def_time_val < 0 || set_def_time_val > 255) { | |
218 | fprintf(stderr, "Invalid default time value: %s\n",optarg); | |
219 | errflg ++; | |
220 | } | |
221 | break; | |
222 | case 'g': ++get; break; | |
223 | case 'G': ++get_def; break; | |
224 | default: | |
225 | errflg ++; | |
226 | } | |
227 | } | |
228 | numfiles = argc - optind; | |
229 | if(errflg || (numfiles == 0) | |
230 | || (!query && !set && !set_def && | |
231 | !get && !get_def && !set_time && !set_def_time) || | |
232 | (set && set_def) || (set_time && set_def_time) || | |
233 | (get && get_def)) { | |
234 | fprintf(stderr, | |
235 | "Usage: %s [-q [-i interval]]" | |
236 | " ([-s value]|[-S value]) ([-t value]|[-T value])" | |
237 | " [-g|-G] file [file...]\n", | |
238 | argv[0]); | |
239 | exit(1); | |
240 | } | |
241 | ||
242 | global_optind = optind; /* For signal routine. */ | |
243 | ||
244 | if (set || set_def) { | |
245 | for(i = optind;i < argc;i ++) { | |
246 | file = open(argv[i],O_RDONLY); | |
247 | if(file == -1) { | |
248 | fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); | |
249 | exit(1); | |
250 | } | |
251 | if(ioctl(file, | |
252 | set ? CYSETTHRESH : CYSETDEFTHRESH, | |
253 | set ? set_val : set_def_val)) { | |
254 | fprintf(stderr, "Can't set %s to threshold %d: %s\n", | |
255 | argv[i],set?set_val:set_def_val,strerror(errno)); | |
256 | exit(1); | |
257 | } | |
258 | } | |
259 | } | |
260 | if (set_time || set_def_time) { | |
261 | for(i = optind;i < argc;i ++) { | |
262 | file = open(argv[i],O_RDONLY); | |
263 | if(file == -1) { | |
264 | fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); | |
265 | exit(1); | |
266 | } | |
267 | if(ioctl(file, | |
268 | set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT, | |
269 | set_time ? set_time_val : set_def_time_val)) { | |
270 | fprintf(stderr, "Can't set %s to time threshold %d: %s\n", | |
271 | argv[i],set_time?set_time_val:set_def_time_val,strerror(errno)); | |
272 | exit(1); | |
273 | } | |
274 | } | |
275 | } | |
276 | ||
277 | if (get || get_def) { | |
278 | for(i = optind;i < argc;i ++) { | |
279 | file = open(argv[i],O_RDONLY); | |
280 | if(file == -1) { | |
281 | fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); | |
282 | exit(1); | |
283 | } | |
284 | if(ioctl(file, get ? CYGETTHRESH : CYGETDEFTHRESH, &threshold_value)) { | |
285 | fprintf(stderr, "Can't get threshold for %s: %s\n", | |
286 | argv[i],strerror(errno)); | |
287 | exit(1); | |
288 | } | |
289 | if(ioctl(file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, &timeout_value)) { | |
290 | fprintf(stderr, "Can't get timeout for %s: %s\n", | |
291 | argv[i],strerror(errno)); | |
292 | exit(1); | |
293 | } | |
294 | printf("%s: %ld %s threshold and %ld %s timeout\n", | |
295 | argv[i], threshold_value, | |
296 | get?"current":"default", | |
297 | timeout_value, | |
298 | get?"current":"default"); | |
299 | } | |
300 | } | |
301 | ||
302 | if(!query) return 0; /* must have been something earlier */ | |
303 | ||
304 | /* query stuff after this line */ | |
305 | ||
306 | cmon = (struct cyclades_control *) malloc(sizeof (struct cyclades_control) | |
307 | * numfiles); | |
308 | if(!cmon) { | |
309 | perror("malloc failed"); | |
310 | exit(1); | |
311 | } | |
312 | if(signal(SIGINT, summary)|| | |
313 | signal(SIGQUIT, summary)|| | |
314 | signal(SIGTERM, summary)) { | |
315 | perror("Can't set signal handler"); | |
316 | exit(1); | |
317 | } | |
318 | if(gettimeofday(&lasttime,&tz)) { | |
319 | perror("gettimeofday failed"); | |
320 | exit(1); | |
321 | } | |
322 | for(i = optind; i < argc; i ++) { | |
323 | cmon_index = i - optind; | |
324 | cmon[cmon_index].cfile = open(argv[i], O_RDONLY); | |
325 | if(-1 == cmon[cmon_index].cfile) { | |
326 | fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno)); | |
327 | exit(1); | |
328 | } | |
329 | if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) { | |
330 | fprintf(stderr, "Can't issue CYGETMON on %s: %s\n", | |
331 | argv[i],strerror(errno)); | |
332 | exit(1); | |
333 | } | |
334 | summary(-1); | |
335 | if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) { | |
336 | fprintf(stderr, "Can't get threshold for %s: %s\n", | |
337 | argv[i],strerror(errno)); | |
338 | exit(1); | |
339 | } | |
340 | if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) { | |
341 | fprintf(stderr, "Can't get timeout for %s: %s\n", | |
342 | argv[i],strerror(errno)); | |
343 | exit(1); | |
344 | } | |
345 | } | |
346 | while(1) { | |
347 | sleep(interval); | |
348 | ||
349 | if(gettimeofday(&thistime,&tz)) { | |
350 | perror("gettimeofday failed"); | |
351 | exit(1); | |
352 | } | |
353 | diff = dtime(&thistime, &lasttime); | |
354 | mvtime(&lasttime, &thistime); | |
355 | ||
356 | for(i = optind; i < argc; i ++) { | |
357 | cmon_index = i - optind; | |
358 | if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) { | |
359 | fprintf(stderr, "Can't issue CYGETMON on %s: %s\n", | |
360 | argv[i],strerror(errno)); | |
361 | exit(1); | |
362 | } | |
363 | if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) { | |
364 | fprintf(stderr, "Can't get threshold for %s: %s\n", | |
365 | argv[i],strerror(errno)); | |
366 | exit(1); | |
367 | } | |
368 | if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) { | |
369 | fprintf(stderr, "Can't get timeout for %s: %s\n", | |
370 | argv[i],strerror(errno)); | |
371 | exit(1); | |
372 | } | |
373 | ||
374 | xfer_rate = cywork.char_count/diff; | |
375 | #ifdef XMIT | |
376 | xmit_rate = cywork.send_count/diff; | |
377 | #endif | |
378 | ||
379 | if(threshold_value != cmon[cmon_index].threshold_value || | |
380 | timeout_value != cmon[cmon_index].timeout_value) { | |
381 | summary(-2); | |
382 | /* Note that the summary must come before the setting of */ | |
383 | /* threshold_value */ | |
384 | cmon[cmon_index].threshold_value = threshold_value; | |
385 | cmon[cmon_index].timeout_value = timeout_value; | |
386 | } else { | |
387 | /* Don't record this first cycle after change */ | |
388 | if(xfer_rate > cmon[cmon_index].maxtran) | |
389 | cmon[cmon_index].maxtran = xfer_rate; | |
390 | #ifdef XMIT | |
391 | if(xmit_rate > cmon[cmon_index].maxxmit) | |
392 | cmon[cmon_index].maxxmit = xmit_rate; | |
393 | #endif | |
394 | if(cywork.char_max > cmon[cmon_index].maxmax) | |
395 | cmon[cmon_index].maxmax = cywork.char_max; | |
396 | } | |
397 | ||
398 | #ifdef XMIT | |
399 | printf("%s: %lu ints, %lu/%lu chars; " | |
400 | "fifo: %lu thresh, %lu tmout, " | |
401 | "%lu max, %lu now\n", | |
402 | argv[i], | |
403 | cywork.int_count,cywork.char_count,cywork.send_count, | |
404 | threshold_value,timeout_value, | |
405 | cywork.char_max,cywork.char_last); | |
406 | printf(" %f int/sec; %f rec, %f send (char/sec)\n", | |
407 | cywork.int_count/diff, | |
408 | xfer_rate, | |
409 | xmit_rate); | |
410 | #else | |
411 | printf("%s: %lu ints, %lu chars; " | |
412 | "fifo: %lu thresh, %lu tmout, " | |
413 | "%lu max, %lu now\n", | |
414 | argv[i], | |
415 | cywork.int_count,cywork.char_count, | |
416 | threshold_value,timeout_value, | |
417 | cywork.char_max,cywork.char_last); | |
418 | printf(" %f int/sec; %f rec (char/sec)\n", | |
419 | cywork.int_count/diff, | |
420 | xfer_rate); | |
421 | #endif | |
422 | memcpy(&cmon[cmon_index].c, &cywork, sizeof (struct cyclades_monitor)); | |
423 | } | |
424 | } | |
425 | ||
426 | return 0; | |
427 | } |