pcibx.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /*
  2. Catalyst PCIBX32 PCI Extender control utility
  3. Copyright (c) 2006-2009 Michael Buesch <mb@bu3sch.de>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; see the file COPYING. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. #include "pcibx.h"
  18. #include "pcibx_device.h"
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <stdint.h>
  22. #include <sched.h>
  23. #include <signal.h>
  24. #include <stdarg.h>
  25. #include <time.h>
  26. #include <sys/time.h>
  27. struct cmdline_args cmdargs;
  28. struct timeval starttime;
  29. /* Subtract the `struct timeval' values X and Y,
  30. * storing the result in RESULT.
  31. * Return 1 if the difference is negative, otherwise 0.
  32. *
  33. * Taken from the glibc docs, so should be
  34. * Copyright (c) Free Software Foundation
  35. */
  36. static int timeval_subtract(struct timeval *result,
  37. struct timeval *x,
  38. struct timeval *y)
  39. {
  40. int nsec;
  41. /* Perform the carry for the later subtraction by updating y. */
  42. if (x->tv_usec < y->tv_usec) {
  43. nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
  44. y->tv_usec -= 1000000 * nsec;
  45. y->tv_sec += nsec;
  46. }
  47. if (x->tv_usec - y->tv_usec > 1000000) {
  48. nsec = (x->tv_usec - y->tv_usec) / 1000000;
  49. y->tv_usec += 1000000 * nsec;
  50. y->tv_sec -= nsec;
  51. }
  52. /* Compute the time remaining to wait.
  53. * tv_usec is certainly positive. */
  54. result->tv_sec = x->tv_sec - y->tv_sec;
  55. result->tv_usec = x->tv_usec - y->tv_usec;
  56. /* Return 1 if result is negative. */
  57. return x->tv_sec < y->tv_sec;
  58. }
  59. #define print_data(description, format, units, ...) do { \
  60. struct timeval tmp, tv; \
  61. int err; \
  62. \
  63. if (cmdargs.verbose >= 1) { \
  64. err = gettimeofday(&tmp, NULL); \
  65. if (err) { \
  66. prerror("gettimeofday() failure!\n"); \
  67. break; \
  68. } \
  69. err = timeval_subtract(&tv, &tmp, &starttime); \
  70. if (err) { \
  71. prerror("timeval_subtract() went negative!\n"); \
  72. break; \
  73. } \
  74. prinfo("%ld.%06ld " format " # ", \
  75. tv.tv_sec, tv.tv_usec, \
  76. __VA_ARGS__); \
  77. } \
  78. prinfo(description ": " format " " units "\n", __VA_ARGS__); \
  79. } while (0)
  80. static int send_commands(struct pcibx_device *dev)
  81. {
  82. struct pcibx_command *cmd;
  83. uint8_t v;
  84. float f;
  85. int i;
  86. for (i = 0; i < cmdargs.nr_commands; i++) {
  87. cmd = &(cmdargs.commands[i]);
  88. switch (cmd->id) {
  89. case CMD_GLOB:
  90. pcibx_cmd_global_pwr(dev, cmd->u.boolean);
  91. break;
  92. case CMD_UUT:
  93. pcibx_cmd_uut_pwr(dev, cmd->u.boolean);
  94. break;
  95. case CMD_PRINTBOARDID:
  96. v = pcibx_cmd_getboardid(dev);
  97. print_data("Board ID", "0x%02X", "", v);
  98. break;
  99. case CMD_PRINTFIRMREV:
  100. v = pcibx_cmd_getfirmrev(dev);
  101. print_data("Firmware revision", "0x%02X", "", v);
  102. break;
  103. case CMD_PRINTSTATUS:
  104. v = pcibx_cmd_getstatus(dev);
  105. print_data("Board status", "%s; %s; %s; %s; %s", "",
  106. (v & PCIBX_STATUS_RSTDEASS) ? "RST# de-asserted"
  107. : "RST# asserted",
  108. (v & PCIBX_STATUS_64BIT) ? "64-bit operation established"
  109. : "No 64-bit handshake detected",
  110. (v & PCIBX_STATUS_32BIT) ? "32-bit operation established"
  111. : "No 32-bit handshake detected",
  112. (v & PCIBX_STATUS_MHZ) ? "66 Mhz enabled slot"
  113. : "33 Mhz enabled slot",
  114. (v & PCIBX_STATUS_DUTASS) ? "DUT asserted"
  115. : "DUT not fully asserted");
  116. break;
  117. case CMD_CLEARBITSTAT:
  118. pcibx_cmd_clearbitstat(dev);
  119. break;
  120. case CMD_AUX5:
  121. pcibx_cmd_aux5(dev, cmd->u.boolean);
  122. break;
  123. case CMD_AUX33:
  124. pcibx_cmd_aux33(dev, cmd->u.boolean);
  125. break;
  126. case CMD_MEASUREFREQ:
  127. f = pcibx_cmd_sysfreq(dev);
  128. print_data("Measured system frequency", "%f", "Mhz", f);
  129. break;
  130. case CMD_MEASUREV25REF:
  131. f = pcibx_cmd_measure(dev, MEASURE_V25REF);
  132. print_data("Measured +2.5V Reference", "%f", "Volt", f);
  133. break;
  134. case CMD_MEASUREV12UUT:
  135. f = pcibx_cmd_measure(dev, MEASURE_V12UUT);
  136. print_data("Measured +12V UUT", "%f", "Volt", f);
  137. break;
  138. case CMD_MEASUREV5UUT:
  139. f = pcibx_cmd_measure(dev, MEASURE_V5UUT);
  140. print_data("Measured +5V UUT", "%f", "Volt", f);
  141. break;
  142. case CMD_MEASUREV33UUT:
  143. f = pcibx_cmd_measure(dev, MEASURE_V33UUT);
  144. print_data("Measured +33V UUT", "%f", "Volt", f);
  145. break;
  146. case CMD_MEASUREV5AUX:
  147. f = pcibx_cmd_measure(dev, MEASURE_V5AUX);
  148. print_data("Measured +5V AUX", "%f", "Volt", f);
  149. break;
  150. case CMD_MEASUREA5:
  151. f = pcibx_cmd_measure(dev, MEASURE_A5);
  152. print_data("Measured +5V Current", "%f", "Ampere", f);
  153. break;
  154. case CMD_MEASUREA12:
  155. f = pcibx_cmd_measure(dev, MEASURE_A12);
  156. print_data("Measured +12V Current", "%f", "Ampere", f);
  157. break;
  158. case CMD_MEASUREA33:
  159. f = pcibx_cmd_measure(dev, MEASURE_A33);
  160. print_data("Measured +3.3V Current", "%f", "Ampere", f);
  161. break;
  162. case CMD_FASTRAMP:
  163. pcibx_cmd_ramp(dev, cmd->u.boolean);
  164. break;
  165. case CMD_RST:
  166. pcibx_cmd_rst(dev, cmd->u.d);
  167. break;
  168. case CMD_RSTDEFAULT:
  169. pcibx_cmd_rstdefault(dev);
  170. break;
  171. case CMD_GETPME:
  172. v = pcibx_cmd_getpme(dev);
  173. print_data("PME# status", "0x%02X", "", v);
  174. break;
  175. default:
  176. internal_error("invalid command");
  177. return -1;
  178. }
  179. }
  180. if (cmdargs.verbose >= 2)
  181. prinfo("All commands sent.\n");
  182. return 0;
  183. }
  184. static int request_priority(void)
  185. {
  186. struct sched_param param;
  187. int err;
  188. param.sched_priority = sched_get_priority_max(cmdargs.sched);
  189. err = sched_setscheduler(0, cmdargs.sched, &param);
  190. if (err) {
  191. prerror("Could not set scheduling policy (%s).\n",
  192. strerror(errno));
  193. }
  194. return err;
  195. }
  196. static void print_banner(void)
  197. {
  198. prinfo("Catalyst PCIBX32 PCI Extender control utility version " VERSION "\n"
  199. "\n"
  200. "Copyright 2006-2009 Michael Buesch <mb@bu3sch.de>\n"
  201. "Licensed under the GNU General Public License v2+\n"
  202. "\n");
  203. }
  204. static void print_usage(int argc, char **argv)
  205. {
  206. prinfo("Usage: %s [OPTION]\n", argv[0]);
  207. prinfo(" -V|--verbose LEVEL Verbosity level 0-2 (default: 0)\n");
  208. prinfo(" -v|--version Print version\n");
  209. prinfo(" -h|--help Print this help\n");
  210. prinfo("\n");
  211. prinfo(" -p|--port /dev/parportX Parport device (Default: /dev/parport0)\n");
  212. prinfo(" -P|--pci1 BOOL If true, PCI_1 (default), otherwise PCI_2. (See JP15)\n");
  213. prinfo(" -s|--sched POLICY Scheduling policy (normal, fifo, rr)\n");
  214. prinfo(" -n|--nrcycle COUNT Cycle COUNT times. 0 = infinite (default: 1)\n");
  215. prinfo(" -d|--delay DELAY DELAY msecs after each cycle. Default 0\n");
  216. prinfo("\n");
  217. prinfo("Device commands\n");
  218. prinfo(" --cmd-glob ON/OFF Turn Global power ON/OFF (does not turn ON UUT Voltages)\n");
  219. prinfo(" --cmd-uut ON/OFF Turn UUT Voltages ON/OFF (also turns Global power ON)\n");
  220. prinfo(" --cmd-printboardid Print the Board ID\n");
  221. prinfo(" --cmd-printfirmrev Print the Firmware revision\n");
  222. prinfo(" --cmd-printstatus Print the Board Status Bits\n");
  223. prinfo(" --cmd-clearbitstat Clear 32/64 bit status\n");
  224. prinfo(" --cmd-aux5 ON/OFF Turn +5V Aux ON or OFF\n");
  225. prinfo(" --cmd-aux33 ON/OFF Turn +3.3V Aux ON or OFF\n");
  226. prinfo(" --cmd-measurefreq Measure system frequency\n");
  227. prinfo(" --cmd-measurev25ref Measure +2.5V Reference\n");
  228. prinfo(" --cmd-measurev12uut Measure +12V UUT\n");
  229. prinfo(" --cmd-measurev5uut Measure +5V UUT\n");
  230. prinfo(" --cmd-measurev33uut Measure +3.3V UUT\n");
  231. prinfo(" --cmd-measurev5aux Measure +5V AUX\n");
  232. prinfo(" --cmd-measurea5 Measure +5V Current\n");
  233. prinfo(" --cmd-measurea12 Measure +12V Current\n");
  234. prinfo(" --cmd-measurea33 Measure +3.3V Current\n");
  235. prinfo(" --cmd-fastramp ON/OFF Select slow/fast +5V ramp\n");
  236. prinfo(" --cmd-rst 0.150 Set RST# (reset) delay (in seconds)\n");
  237. prinfo(" --cmd-rstdefault Set RST# to default (150msec)\n");
  238. }
  239. #define ARG_MATCH 0
  240. #define ARG_NOMATCH 1
  241. #define ARG_ERROR -1
  242. static int do_cmp_arg(char **argv, int *pos,
  243. const char *template,
  244. int allow_merged,
  245. char **param)
  246. {
  247. char *arg;
  248. char *next_arg;
  249. size_t arg_len, template_len;
  250. arg = argv[*pos];
  251. next_arg = argv[*pos + 1];
  252. arg_len = strlen(arg);
  253. template_len = strlen(template);
  254. if (param) {
  255. /* Maybe we have a merged parameter here.
  256. * A merged parameter is "-pfoobar" for example.
  257. */
  258. if (allow_merged && arg_len > template_len) {
  259. if (memcmp(arg, template, template_len) == 0) {
  260. *param = arg + template_len;
  261. return ARG_MATCH;
  262. }
  263. return ARG_NOMATCH;
  264. } else if (arg_len != template_len)
  265. return ARG_NOMATCH;
  266. *param = next_arg;
  267. }
  268. if (strcmp(arg, template) == 0) {
  269. if (param) {
  270. /* Skip the parameter on the next iteration. */
  271. (*pos)++;
  272. if (*param == 0) {
  273. prerror("%s needs a parameter\n", arg);
  274. return ARG_ERROR;
  275. }
  276. }
  277. return ARG_MATCH;
  278. }
  279. return ARG_NOMATCH;
  280. }
  281. /* Simple and lean command line argument parsing. */
  282. static int cmp_arg(char **argv, int *pos,
  283. const char *long_template,
  284. const char *short_template,
  285. char **param)
  286. {
  287. int err;
  288. if (long_template) {
  289. err = do_cmp_arg(argv, pos, long_template, 0, param);
  290. if (err == ARG_MATCH || err == ARG_ERROR)
  291. return err;
  292. }
  293. err = ARG_NOMATCH;
  294. if (short_template)
  295. err = do_cmp_arg(argv, pos, short_template, 1, param);
  296. return err;
  297. }
  298. #define arg_match(argv, i, tlong, tshort, param) \
  299. ({ \
  300. int res = cmp_arg((argv), (i), (tlong), \
  301. (tshort), (param)); \
  302. if ((res) == ARG_ERROR) \
  303. goto error; \
  304. ((res) == ARG_MATCH); \
  305. })
  306. #if 0
  307. static int parse_hexval(const char *str,
  308. uint32_t *value,
  309. const char *param)
  310. {
  311. uint32_t v;
  312. if (strncmp(str, "0x", 2) != 0)
  313. goto error;
  314. str += 2;
  315. errno = 0;
  316. v = strtoul(str, NULL, 16);
  317. if (errno)
  318. goto error;
  319. *value = v;
  320. return 0;
  321. error:
  322. if (param) {
  323. prerror("%s value parsing error. Format: 0xFFFFFFFF\n",
  324. param);
  325. }
  326. return -1;
  327. }
  328. #endif
  329. static int parse_bool(const char *str,
  330. const char *param)
  331. {
  332. if (strcmp(str, "1") == 0)
  333. return 1;
  334. if (strcmp(str, "0") == 0)
  335. return 0;
  336. if (strcasecmp(str, "true") == 0)
  337. return 1;
  338. if (strcasecmp(str, "false") == 0)
  339. return 0;
  340. if (strcasecmp(str, "yes") == 0)
  341. return 1;
  342. if (strcasecmp(str, "no") == 0)
  343. return 0;
  344. if (strcasecmp(str, "on") == 0)
  345. return 1;
  346. if (strcasecmp(str, "off") == 0)
  347. return 0;
  348. if (param) {
  349. prerror("%s boolean parsing error. Format: BOOL\n",
  350. param);
  351. }
  352. return -1;
  353. }
  354. static int parse_double(const char *str,
  355. double *value,
  356. const char *param)
  357. {
  358. double v;
  359. errno = 0;
  360. v = strtod(str, NULL);
  361. if (errno)
  362. goto error;
  363. *value = v;
  364. return 0;
  365. error:
  366. if (param) {
  367. prerror("%s value parsing error. Format: 0.00123\n",
  368. param);
  369. }
  370. return -1;
  371. }
  372. static int parse_int(const char *str,
  373. int *value,
  374. const char *param)
  375. {
  376. int v;
  377. errno = 0;
  378. v = strtol(str, NULL, 10);
  379. if (errno)
  380. goto error;
  381. *value = v;
  382. return 0;
  383. error:
  384. if (param) {
  385. prerror("%s value parsing error. Format: 1234\n",
  386. param);
  387. }
  388. return -1;
  389. }
  390. static int add_command(enum command_id cmd)
  391. {
  392. if (cmdargs.nr_commands == MAX_COMMAND) {
  393. prerror("Maximum number of commands exceed.\n");
  394. return -1;
  395. }
  396. cmdargs.commands[cmdargs.nr_commands++].id = cmd;
  397. return 0;
  398. }
  399. static int add_boolcommand(enum command_id cmd,
  400. const char *str,
  401. const char *param)
  402. {
  403. int boolean;
  404. if (cmdargs.nr_commands == MAX_COMMAND) {
  405. prerror("Maximum number of commands exceed.\n");
  406. return -1;
  407. }
  408. boolean = parse_bool(str, param);
  409. if (boolean < 0)
  410. return -1;
  411. cmdargs.commands[cmdargs.nr_commands].id = cmd;
  412. cmdargs.commands[cmdargs.nr_commands].u.boolean = !!boolean;
  413. cmdargs.nr_commands++;
  414. return 0;
  415. }
  416. static int add_doublecommand(enum command_id cmd,
  417. const char *str,
  418. const char *param)
  419. {
  420. int err;
  421. double value;
  422. if (cmdargs.nr_commands == MAX_COMMAND) {
  423. prerror("Maximum number of commands exceed.\n");
  424. return -1;
  425. }
  426. err = parse_double(str, &value, param);
  427. if (err)
  428. return err;
  429. cmdargs.commands[cmdargs.nr_commands].id = cmd;
  430. cmdargs.commands[cmdargs.nr_commands].u.d = value;
  431. cmdargs.nr_commands++;
  432. return 0;
  433. }
  434. static int parse_args(int argc, char **argv)
  435. {
  436. int i, err;
  437. char *param;
  438. cmdargs.port = "/dev/parport0";
  439. cmdargs.is_PCI_1 = 1;
  440. cmdargs.sched = SCHED_OTHER;
  441. cmdargs.cycle_delay = 0;
  442. cmdargs.nrcycle = 1;
  443. for (i = 1; i < argc; i++) {
  444. if (arg_match(argv, &i, "--version", "-v", 0)) {
  445. print_banner();
  446. return 1;
  447. } else if (arg_match(argv, &i, "--help", "-h", 0)) {
  448. print_banner();
  449. print_usage(argc, argv);
  450. return 1;
  451. } else if (arg_match(argv, &i, "--verbose", "-V", &param)) {
  452. err = parse_int(param, &cmdargs.verbose, "--verbose");
  453. if (err)
  454. goto error;
  455. } else if (arg_match(argv, &i, "--port", "-p", &param)) {
  456. cmdargs.port = param;
  457. } else if (arg_match(argv, &i, "--pci1", "-P", &param)) {
  458. err = parse_bool(param, "--pci1");
  459. if (err < 0)
  460. goto error;
  461. cmdargs.is_PCI_1 = !!err;
  462. } else if (arg_match(argv, &i, "--sched", "-s", &param)) {
  463. if (strcasecmp(param, "normal") == 0)
  464. cmdargs.sched = SCHED_OTHER;
  465. else if (strcasecmp(param, "fifo") == 0)
  466. cmdargs.sched = SCHED_FIFO;
  467. else if (strcasecmp(param, "rr") == 0)
  468. cmdargs.sched = SCHED_RR;
  469. else {
  470. prerror("Invalid parameter to --sched\n");
  471. goto error;
  472. }
  473. } else if (arg_match(argv, &i, "--delay", "-d", &param)) {
  474. err = parse_int(param, &cmdargs.cycle_delay, "--delay");
  475. if (err)
  476. goto error;
  477. } else if (arg_match(argv, &i, "--nrcycle", "-n", &param)) {
  478. err = parse_int(param, &cmdargs.nrcycle, "--nrcycle");
  479. if (err)
  480. goto error;
  481. } else if (arg_match(argv, &i, "--cmd-glob", 0, &param)) {
  482. err = add_boolcommand(CMD_GLOB, param, "--cmd-glob");
  483. if (err)
  484. goto error;
  485. } else if (arg_match(argv, &i, "--cmd-uut", 0, &param)) {
  486. err = add_boolcommand(CMD_UUT, param, "--cmd-uut");
  487. if (err)
  488. goto error;
  489. } else if (arg_match(argv, &i, "--cmd-printboardid", 0, 0)) {
  490. err = add_command(CMD_PRINTBOARDID);
  491. if (err)
  492. goto error;
  493. } else if (arg_match(argv, &i, "--cmd-printfirmrev", 0, 0)) {
  494. err = add_command(CMD_PRINTFIRMREV);
  495. if (err)
  496. goto error;
  497. } else if (arg_match(argv, &i, "--cmd-printstatus", 0, 0)) {
  498. err = add_command(CMD_PRINTSTATUS);
  499. if (err)
  500. goto error;
  501. } else if (arg_match(argv, &i, "--cmd-clearbitstat", 0, 0)) {
  502. err = add_command(CMD_CLEARBITSTAT);
  503. if (err)
  504. goto error;
  505. } else if (arg_match(argv, &i, "--cmd-aux5", 0, &param)) {
  506. err = add_boolcommand(CMD_AUX5, param, "--cmd-aux5");
  507. if (err)
  508. goto error;
  509. } else if (arg_match(argv, &i, "--cmd-aux33", 0, &param)) {
  510. err = add_boolcommand(CMD_AUX33, param, "--cmd-aux33");
  511. if (err)
  512. goto error;
  513. } else if (arg_match(argv, &i, "--cmd-measurefreq", 0, 0)) {
  514. err = add_command(CMD_MEASUREFREQ);
  515. if (err)
  516. goto error;
  517. } else if (arg_match(argv, &i, "--cmd-measurev25ref", 0, 0)) {
  518. err = add_command(CMD_MEASUREV25REF);
  519. if (err)
  520. goto error;
  521. } else if (arg_match(argv, &i, "--cmd-measurev12uut", 0, 0)) {
  522. err = add_command(CMD_MEASUREV12UUT);
  523. if (err)
  524. goto error;
  525. } else if (arg_match(argv, &i, "--cmd-measurev5uut", 0, 0)) {
  526. err = add_command(CMD_MEASUREV5UUT);
  527. if (err)
  528. goto error;
  529. } else if (arg_match(argv, &i, "--cmd-measurev33uut", 0, 0)) {
  530. err = add_command(CMD_MEASUREV33UUT);
  531. if (err)
  532. goto error;
  533. } else if (arg_match(argv, &i, "--cmd-measurev5aux", 0, 0)) {
  534. err = add_command(CMD_MEASUREV5AUX);
  535. if (err)
  536. goto error;
  537. } else if (arg_match(argv, &i, "--cmd-measurea5", 0, 0)) {
  538. err = add_command(CMD_MEASUREA5);
  539. if (err)
  540. goto error;
  541. } else if (arg_match(argv, &i, "--cmd-measurea12", 0, 0)) {
  542. err = add_command(CMD_MEASUREA12);
  543. if (err)
  544. goto error;
  545. } else if (arg_match(argv, &i, "--cmd-measurea33", 0, 0)) {
  546. err = add_command(CMD_MEASUREA33);
  547. if (err)
  548. goto error;
  549. } else if (arg_match(argv, &i, "--cmd-fastramp", 0, &param)) {
  550. err = add_boolcommand(CMD_FASTRAMP, param, "--cmd-fastramp");
  551. if (err)
  552. goto error;
  553. } else if (arg_match(argv, &i, "--cmd-rst", 0, &param)) {
  554. err = add_doublecommand(CMD_RST, param, "--cmd-rst");
  555. if (err)
  556. goto error;
  557. } else if (arg_match(argv, &i, "--cmd-rstdefault", 0, 0)) {
  558. err = add_command(CMD_RSTDEFAULT);
  559. if (err)
  560. goto error;
  561. } else if (arg_match(argv, &i, "--cmd-getpme", 0, 0)) {
  562. err = add_command(CMD_GETPME);
  563. if (err)
  564. goto error;
  565. } else {
  566. prerror("Unrecognized argument: %s\n", argv[i]);
  567. goto error;
  568. }
  569. }
  570. if (cmdargs.nr_commands == 0) {
  571. prerror("No device commands specified.\n\n");
  572. print_usage(argc, argv);
  573. goto error;
  574. }
  575. return 0;
  576. error:
  577. return -1;
  578. }
  579. static void signal_handler(int sig)
  580. {
  581. prinfo("Signal %d received. Terminating.\n", sig);
  582. exit(1);
  583. }
  584. static int setup_sighandler(void)
  585. {
  586. int err;
  587. struct sigaction sa;
  588. sa.sa_handler = signal_handler;
  589. sigemptyset(&sa.sa_mask);
  590. sa.sa_flags = 0;
  591. err = sigaction(SIGINT, &sa, NULL);
  592. err |= sigaction(SIGTERM, &sa, NULL);
  593. if (err)
  594. prerror("sigaction setup failed.\n");
  595. return err;
  596. }
  597. int main(int argc, char **argv)
  598. {
  599. struct pcibx_device dev;
  600. int err;
  601. int nrcycle;
  602. err = setup_sighandler();
  603. if (err)
  604. goto out;
  605. err = parse_args(argc, argv);
  606. if (err == 1)
  607. return 0;
  608. else if (err != 0)
  609. goto out;
  610. err = request_priority();
  611. if (err)
  612. goto out;
  613. err = pcibx_device_init(&dev, cmdargs.port, cmdargs.is_PCI_1);
  614. if (err)
  615. goto out;
  616. gettimeofday(&starttime, NULL);
  617. nrcycle = cmdargs.nrcycle;
  618. if (nrcycle == 0)
  619. nrcycle = -1;
  620. while (1) {
  621. err = send_commands(&dev);
  622. if (err)
  623. goto out_exit_dev;
  624. if (nrcycle > 0)
  625. nrcycle--;
  626. if (nrcycle == 0)
  627. break;
  628. if (cmdargs.cycle_delay)
  629. msleep(cmdargs.cycle_delay);
  630. }
  631. out_exit_dev:
  632. pcibx_device_exit(&dev);
  633. out:
  634. return err ? 1 : 0;
  635. }