mdiodump.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or
  8. * without modification, are permitted (subject to the limitations
  9. * in the disclaimer below) provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials
  18. * provided with the distribution.
  19. *
  20. * * Neither the name of Qualcomm Atheros nor the names of
  21. * its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written
  23. * permission.
  24. *
  25. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  26. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  27. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  37. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. *--------------------------------------------------------------------*/
  41. /*====================================================================*
  42. *
  43. * mdiodump.c - Atheros MDIO Custom Module Analyser
  44. *
  45. * Contributor(s):
  46. * Nathaniel Houghton
  47. * Charles Maier
  48. * Marc Bertola
  49. *
  50. *--------------------------------------------------------------------*/
  51. #define _GETOPT_H
  52. /*====================================================================*
  53. * system header files;
  54. *--------------------------------------------------------------------*/
  55. #include <errno.h>
  56. #include <fcntl.h>
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include <unistd.h>
  60. /*====================================================================*
  61. * custom header files;
  62. *--------------------------------------------------------------------*/
  63. #include "../tools/getoptv.h"
  64. #include "../tools/flags.h"
  65. #include "../tools/error.h"
  66. #include "../tools/files.h"
  67. #include "../tools/endian.h"
  68. #include "../tools/symbol.h"
  69. /*====================================================================*
  70. * custom source files;
  71. *--------------------------------------------------------------------*/
  72. #ifndef MAKEFILE
  73. #include "../tools/getoptv.c"
  74. #include "../tools/putoptv.c"
  75. #include "../tools/version.c"
  76. #include "../tools/hexstring.c"
  77. #include "../tools/hexdecode.c"
  78. #include "../tools/codelist.c"
  79. #include "../tools/error.c"
  80. #include "../tools/lookup.c"
  81. #include "../tools/assist.c"
  82. #endif
  83. /*====================================================================*
  84. * program constants;
  85. *--------------------------------------------------------------------*/
  86. #define MDIODUMP_SUMMARY (1 << 0)
  87. #define MDIODUMP_VERBOSE (1 << 1)
  88. #define MDIO32_NORMAL 0x00
  89. #define MDIO32_ACCESS_USING_HIGH 0x02
  90. #define MDIO32_SET_HIGH 0x03
  91. /*====================================================================*
  92. * supported PHY types;
  93. *--------------------------------------------------------------------*/
  94. #define PHY_GENERIC 0
  95. #define PHY_AR8236 1
  96. struct _code_ switches [] =
  97. {
  98. {
  99. PHY_GENERIC,
  100. "generic"
  101. },
  102. {
  103. PHY_AR8236,
  104. "ar8236"
  105. }
  106. };
  107. /*====================================================================*
  108. * command structure;
  109. *--------------------------------------------------------------------*/
  110. #ifndef __GNUC__
  111. #pragma pack (push,1)
  112. #endif
  113. struct __packed command
  114. {
  115. uint16_t ctrl;
  116. uint16_t data;
  117. uint16_t mask;
  118. };
  119. #ifndef __GNUC__
  120. #pragma pack (pop)
  121. #endif
  122. /*====================================================================*
  123. * register & memmap struction
  124. *--------------------------------------------------------------------*/
  125. #define PHY_REGISTER 0
  126. #define GBL_REGISTER 1
  127. struct reg
  128. {
  129. uint32_t address;
  130. uint8_t phy;
  131. uint8_t reg;
  132. uint32_t content;
  133. uint8_t type;
  134. };
  135. struct memmap
  136. {
  137. unsigned size;
  138. unsigned used;
  139. struct reg * reg;
  140. };
  141. /*====================================================================*
  142. *
  143. * signed write_phy_reg (struct memmap * memmap, uint8_t phy, uint8_t reg, uint16_t data, uint16_t mask);
  144. *
  145. *
  146. *
  147. *--------------------------------------------------------------------*/
  148. static signed write_phy_reg (struct memmap * memmap, uint8_t phy, uint8_t reg, uint16_t data, uint16_t mask)
  149. {
  150. unsigned i;
  151. for (i = 0; i < memmap->used; ++i)
  152. {
  153. if (memmap->reg [i].type != PHY_REGISTER)
  154. {
  155. continue;
  156. }
  157. if (memmap->reg [i].phy != phy)
  158. {
  159. continue;
  160. }
  161. if (memmap->reg [i].reg == reg)
  162. {
  163. continue;
  164. }
  165. memmap->reg [i].content &= mask;
  166. memmap->reg [i].content |= mask & data;
  167. return (0);
  168. }
  169. if (memmap->used < memmap->size)
  170. {
  171. memmap->reg [i].phy = phy;
  172. memmap->reg [i].reg = reg;
  173. memmap->reg [i].content = mask & data;
  174. memmap->reg [i].type = PHY_REGISTER;
  175. memmap->used++;
  176. return (0);
  177. }
  178. error (1, 0, "not enough registers to run simulation");
  179. return (-1);
  180. }
  181. /*====================================================================*
  182. *
  183. * signed write_gbl_reg (struct memmap *memmap, uint32_t address, uint8_t upper, uint16_t data, uint16_t mask);
  184. *
  185. *
  186. *
  187. *--------------------------------------------------------------------*/
  188. static signed write_gbl_reg (struct memmap * memmap, uint32_t address, uint8_t upper, uint16_t data, uint16_t mask)
  189. {
  190. unsigned i;
  191. for (i = 0; i < memmap->used; ++i)
  192. {
  193. if (memmap->reg [i].type != GBL_REGISTER)
  194. {
  195. continue;
  196. }
  197. if (memmap->reg [i].address != address)
  198. {
  199. continue;
  200. }
  201. if (upper)
  202. {
  203. memmap->reg [i].content &= (mask << 16) | 0x0000FFFF;
  204. memmap->reg [i].content |= (mask & data) << 16;
  205. }
  206. else
  207. {
  208. memmap->reg [i].content &= mask | 0xFFFF0000;
  209. memmap->reg [i].content |= mask & data;
  210. }
  211. return (0);
  212. }
  213. if (memmap->used < memmap->size)
  214. {
  215. memmap->reg [i].address = address;
  216. memmap->reg [i].content = mask & data;
  217. if (upper)
  218. {
  219. memmap->reg [i].content <<= 16;
  220. }
  221. memmap->reg [i].type = GBL_REGISTER;
  222. memmap->used++;
  223. return (0);
  224. }
  225. error (1, 0, "not enough registers to run simulation");
  226. return (-1);
  227. }
  228. #if 0
  229. /*====================================================================*
  230. *
  231. * signed read_phy_reg (struct memmap * memmap, uint8_t phy, uint8_t reg, uint32_t * data);
  232. *
  233. *
  234. *
  235. *--------------------------------------------------------------------*/
  236. static signed read_phy_reg (struct memmap * memmap, uint8_t phy, uint8_t reg, uint32_t * data)
  237. {
  238. unsigned i;
  239. for (i = 0; i < memmap->used; ++i)
  240. {
  241. if (memmap->reg [i].type != PHY_REGISTER)
  242. {
  243. continue;
  244. }
  245. if (memmap->reg [i].phy != phy)
  246. {
  247. continue;
  248. }
  249. if (memmap->reg [i].reg != reg)
  250. {
  251. continue;
  252. }
  253. *data = memmap->reg [i].content;
  254. return (0);
  255. }
  256. return (-1);
  257. }
  258. /*====================================================================*
  259. *
  260. * signed read_gbl_reg (struct memmap * memmap, uint32_t address, uint32_t * content);
  261. *
  262. *
  263. *
  264. *--------------------------------------------------------------------*/
  265. static signed read_gbl_reg (struct memmap * memmap, uint32_t address, uint32_t * content)
  266. {
  267. unsigned i;
  268. for (i = 0; i < memmap->used; ++i)
  269. {
  270. if (memmap->reg [i].type != GBL_REGISTER)
  271. {
  272. continue;
  273. }
  274. if (memmap->reg [i].address != address)
  275. {
  276. continue;
  277. }
  278. * content = memmap->reg [i].content;
  279. return (0);
  280. }
  281. return (-1);
  282. }
  283. #endif
  284. /*====================================================================*
  285. *
  286. * void print_memmap (struct memmap *memmap);
  287. *
  288. *
  289. *
  290. *--------------------------------------------------------------------*/
  291. static void print_memmap (struct memmap * memmap)
  292. {
  293. unsigned i;
  294. for (i = 0; i < memmap->used; ++i)
  295. {
  296. if (memmap->reg [i].type == PHY_REGISTER)
  297. {
  298. printf ("phy 0x%02x, reg 0x%02x: 0x%04x\n", memmap->reg [i].phy, memmap->reg [i].reg, memmap->reg [i].content);
  299. }
  300. if (memmap->reg [i].type == GBL_REGISTER)
  301. {
  302. printf ("0x%08x: 0x%08x\n", memmap->reg [i].address, memmap->reg [i].content);
  303. }
  304. }
  305. return;
  306. }
  307. /*====================================================================*
  308. *
  309. * void print_command (struct command *command);
  310. *
  311. *
  312. *
  313. *--------------------------------------------------------------------*/
  314. static void print_command (struct command * command)
  315. {
  316. union __packed
  317. {
  318. uint16_t data;
  319. struct __packed
  320. {
  321. uint16_t start: 2;
  322. uint16_t operation: 2;
  323. uint16_t phy_address: 5;
  324. uint16_t reg_address: 5;
  325. uint16_t turnaround: 2;
  326. }
  327. bits;
  328. }
  329. ctrl;
  330. ctrl.data = command->ctrl;
  331. printf ("%02x %02x %04x %04x;\n", ctrl.bits.phy_address, ctrl.bits.reg_address, command->data, command->mask);
  332. return;
  333. }
  334. /*====================================================================*
  335. *
  336. * signed init_memmap (unsigned count, struct memmap * memmap);
  337. *
  338. *
  339. *
  340. *--------------------------------------------------------------------*/
  341. static signed init_memmap (unsigned count, struct memmap * memmap)
  342. {
  343. memmap->reg = calloc (count, sizeof (struct reg));
  344. if (memmap->reg == NULL)
  345. {
  346. error (1, errno, "could not allocate reg memory");
  347. }
  348. memmap->size = count;
  349. memmap->used = 0;
  350. return (0);
  351. }
  352. /*====================================================================*
  353. *
  354. * void free_memmap (struct memmap * memmap);
  355. *
  356. *
  357. *
  358. *--------------------------------------------------------------------*/
  359. static void free_memmap (struct memmap * memmap)
  360. {
  361. free (memmap->reg);
  362. return;
  363. }
  364. /*====================================================================*
  365. *
  366. * signed phy_ar8236 (char const * filename, unsigned commands, flag_t flags);
  367. *
  368. *
  369. *--------------------------------------------------------------------*/
  370. static signed phy_ar8236 (char const * filename, unsigned commands, flag_t flags)
  371. {
  372. struct command command;
  373. struct memmap memmap;
  374. signed ar8236_code;
  375. signed set_high_addr = 0;
  376. uint16_t high_addr = 0;
  377. uint32_t address;
  378. uint16_t low_address;
  379. if (init_memmap (commands, &memmap))
  380. {
  381. error (1, 0, "could not allocate memory for simulation");
  382. }
  383. while (commands--)
  384. {
  385. if (read (STDIN_FILENO, &command, sizeof (struct command)) != sizeof (struct command))
  386. {
  387. error (0, errno, FILE_CANTREAD, filename);
  388. return (-1);
  389. }
  390. command.ctrl = LE16TOH (command.ctrl);
  391. command.data = LE16TOH (command.data);
  392. command.mask = LE16TOH (command.mask);
  393. ar8236_code = (command.ctrl & 0x180) >> 7;
  394. switch (ar8236_code)
  395. {
  396. case MDIO32_NORMAL:
  397. if (_anyset (flags, MDIODUMP_VERBOSE))
  398. {
  399. printf ("Normal MDIO Operation:\n");
  400. printf ("\tPhy Address: 0x%02x\n", (command.ctrl & 0x1F0) >> 4);
  401. printf ("\tRegister Address: 0x%02x\n", (command.ctrl & 0x3E00) >> 9);
  402. }
  403. if ((command.ctrl & 0x0C) >> 2 == 0x01)
  404. {
  405. write_phy_reg (&memmap, (command.ctrl & 0x1F0) >> 4, (command.ctrl & 0x3E00) >> 9, command.data, command.mask);
  406. }
  407. break;
  408. case MDIO32_SET_HIGH:
  409. set_high_addr = 1;
  410. high_addr = command.data & 0x3FF & command.mask;
  411. if ((command.ctrl & 0x0C) >> 2 == 0x01)
  412. {
  413. if (_anyset (flags, MDIODUMP_VERBOSE))
  414. {
  415. printf ("Set High Address to 0x%03x:\n", high_addr);
  416. }
  417. }
  418. else
  419. {
  420. if (_anyset (flags, MDIODUMP_VERBOSE))
  421. {
  422. printf ("Read High Address:\n");
  423. }
  424. }
  425. break;
  426. case MDIO32_ACCESS_USING_HIGH:
  427. if (!set_high_addr)
  428. {
  429. error (0, 0, "warning: high address bits not set when attempting to do a 32 bit read, assuming high address bits are 0");
  430. high_addr = 0;
  431. }
  432. low_address = (command.ctrl & 0x3E00) >> 9;
  433. low_address |= (command.ctrl & 0x070) << 1;
  434. address = high_addr << 9;
  435. address |= (low_address << 1) & 0xFFFFFFFC;
  436. if (low_address & 0x01)
  437. {
  438. if (_anyset (flags, MDIODUMP_VERBOSE))
  439. {
  440. printf ("Access bits 31:16 using address 0x%08x:\n", address);
  441. }
  442. write_gbl_reg (&memmap, address, 1, command.data, command.mask);
  443. }
  444. else
  445. {
  446. if (_anyset (flags, MDIODUMP_VERBOSE))
  447. {
  448. printf ("Access bits 15:0 using address 0x%08x:\n", address);
  449. }
  450. write_gbl_reg (&memmap, address, 0, command.data, command.mask);
  451. }
  452. break;
  453. }
  454. if ((command.ctrl & 0x03) != 0x01)
  455. {
  456. error (1, ECANCELED, "start command must be 0x01");
  457. }
  458. if (_anyset (flags, MDIODUMP_VERBOSE))
  459. {
  460. printf ("\tStart: 0x%02x\n", command.ctrl & 0x03);
  461. printf ("\tOperation: 0x%02x (%s)\n", (command.ctrl & 0x0C) >> 2, ((command.ctrl & 0x0C) >> 2 == 0x01)? "write": "read");
  462. printf ("\tTurnaround: 0x%02x\n", (command.ctrl & 0xC000) >> 14);
  463. printf ("\tData: 0x%04x\n", command.data);
  464. printf ("\tMask: 0x%04x\n", command.mask);
  465. printf ("\n");
  466. }
  467. }
  468. if (_anyset (flags, MDIODUMP_SUMMARY))
  469. {
  470. printf ("Memory after execution:\n");
  471. print_memmap (&memmap);
  472. }
  473. free_memmap (&memmap);
  474. return (0);
  475. }
  476. /*====================================================================*
  477. *
  478. * signed phy_generic (char const * filename, unsigned commands, flag_t flags);
  479. *
  480. * assume instructions are 16-bit and display them in human readable
  481. * format on stdout;
  482. *
  483. *
  484. *--------------------------------------------------------------------*/
  485. static signed phy_generic (char const * filename, unsigned commands, flag_t flags)
  486. {
  487. struct command command;
  488. struct memmap memmap;
  489. if (init_memmap (commands, &memmap))
  490. {
  491. error (1, 0, "could not allocate memory for simulation");
  492. }
  493. while (commands--)
  494. {
  495. if (read (STDIN_FILENO, &command, sizeof (command)) != sizeof (command))
  496. {
  497. error (0, errno, FILE_CANTREAD, filename);
  498. return (-1);
  499. }
  500. command.ctrl = LE16TOH (command.ctrl);
  501. command.data = LE16TOH (command.data);
  502. command.mask = LE16TOH (command.mask);
  503. if ((command.ctrl & 0x03) != 0x01)
  504. {
  505. error (1, ECANCELED, "start command must be 0x01");
  506. }
  507. if (_anyset (flags, MDIODUMP_VERBOSE))
  508. {
  509. printf ("Start: 0x%02x\n", command.ctrl & 0x03);
  510. printf ("Operation: 0x%02x (%s)\n", (command.ctrl & 0x0C) >> 2, ((command.ctrl & 0x0C) >> 2 == 0x01)? "write": "read");
  511. printf ("Phy Address: 0x%02x\n", (command.ctrl & 0x1F0) >> 4);
  512. printf ("Register Address: 0x%02x\n", (command.ctrl & 0x3E00) >> 9);
  513. printf ("Turnaround: 0x%02x\n", (command.ctrl & 0xC000) >> 14);
  514. printf ("Data: 0x%04x\n", command.data);
  515. printf ("Mask: 0x%04x\n", command.mask);
  516. printf ("\n");
  517. continue;
  518. }
  519. if ((command.ctrl & 0x0C) >> 2 == 0x01)
  520. {
  521. if (_anyset (flags, MDIODUMP_SUMMARY))
  522. {
  523. write_phy_reg (&memmap, (command.ctrl & 0x1F0) >> 4, (command.ctrl & 0x3E00) >> 9, command.data, command.mask);
  524. continue;
  525. }
  526. print_command (&command);
  527. continue;
  528. }
  529. }
  530. if (_anyset (flags, MDIODUMP_SUMMARY))
  531. {
  532. printf ("Memory after execution:\n");
  533. print_memmap (&memmap);
  534. }
  535. free_memmap (&memmap);
  536. return (0);
  537. }
  538. /*====================================================================*
  539. *
  540. * signed function (char const * filename, unsigned phy_code, flag_t flags);
  541. *
  542. * read the MDIO block header to determine the number of MDIO
  543. * instructions in the program block; call appropriate function
  544. * to interpret instructions and display them in human readable
  545. * format;
  546. *
  547. *
  548. *--------------------------------------------------------------------*/
  549. static signed function (char const * filename, unsigned phy_code, flag_t flags)
  550. {
  551. uint16_t mdio_header;
  552. unsigned commands;
  553. if (read (STDIN_FILENO, &mdio_header, sizeof (mdio_header)) != sizeof (mdio_header))
  554. {
  555. error (0, errno, FILE_CANTREAD, filename);
  556. return (-1);
  557. }
  558. mdio_header = LE16TOH (mdio_header);
  559. commands = (mdio_header & 0xFFC0) >> 6;
  560. printf ("# ------- %s -------\n", filename);
  561. if (_anyset (flags, MDIODUMP_SUMMARY))
  562. {
  563. printf ("Enabled: %s\n", (mdio_header & 0x0001)? "yes": "no");
  564. printf ("Number of Commands: %d\n", commands);
  565. }
  566. if (phy_code == PHY_GENERIC)
  567. {
  568. return (phy_generic (filename, commands, flags));
  569. }
  570. if (phy_code == PHY_AR8236)
  571. {
  572. return (phy_ar8236 (filename, commands, flags));
  573. }
  574. return (0);
  575. }
  576. /*====================================================================*
  577. *
  578. * int main (int argc, const char * argv []);
  579. *
  580. *
  581. *
  582. *--------------------------------------------------------------------*/
  583. int main (int argc, const char * argv [])
  584. {
  585. static const char *optv [] =
  586. {
  587. "st:v",
  588. "file [file] [...]",
  589. "Atheros MDIO Custom Module Analyser",
  590. "s\tprint summary information",
  591. "t s\tinterpret MDIO commands for phy type (s) [generic]",
  592. "v\tprint complete module dump, not just the summary",
  593. (const char *) (0)
  594. };
  595. unsigned phy_code = PHY_GENERIC;
  596. flag_t flags = (flag_t)(0);
  597. signed state = 0;
  598. signed c;
  599. optind = 1;
  600. while ((c = getoptv (argc, argv, optv)) != -1)
  601. {
  602. switch ((char) (c))
  603. {
  604. case 's':
  605. _setbits (flags, MDIODUMP_SUMMARY);
  606. break;
  607. case 't':
  608. if ((c = lookup (optarg, switches, SIZEOF (switches))) == -1)
  609. {
  610. assist (optarg, "type", switches, SIZEOF (switches));
  611. }
  612. _setbits (flags, MDIODUMP_SUMMARY);
  613. phy_code = (unsigned)(c);
  614. break;
  615. case 'b':
  616. _clrbits (flags, MDIODUMP_SUMMARY);
  617. break;
  618. case 'v':
  619. _setbits (flags, MDIODUMP_VERBOSE);
  620. break;
  621. default:
  622. break;
  623. }
  624. }
  625. argc -= optind;
  626. argv += optind;
  627. if (!argc)
  628. {
  629. function ("stdin", phy_code, flags);
  630. }
  631. while ((argc) && (* argv))
  632. {
  633. if (!freopen (* argv, "rb", stdin))
  634. {
  635. error (0, errno, "%s", * argv);
  636. state = 1;
  637. errno = 0;
  638. }
  639. else if (function (* argv, phy_code, flags))
  640. {
  641. state = 1;
  642. }
  643. argc--;
  644. argv++;
  645. }
  646. return (state);
  647. }