home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2013 / 2013.06.linuxmafia.com / linuxmafia.com / pub / hardware / 3c5x9setup.c < prev    next >
C/C++ Source or Header  |  2002-09-11  |  17KB  |  532 lines

  1. /* 3c5x9setup.c: Setup program for 3Com EtherLink III ethercards.
  2.  
  3.    Copyright 1994-2000 by Donald Becker.
  4.  
  5.    This is a EEPROM setup and diagnostic program for the 3Com 3c5x9 series
  6.    ethercards.  Most products with "EtherLink III" in the name are supported,
  7.    including
  8.     3c509, 3c529, 3c579  (ISA, MCA, EISA, but not PCI)
  9.     3c556 3c562, 3c563, 3c574 and other PCMCIA (but not CardBus) cards
  10.    The 'B' and 'C' suffix versions are supported, as are the various
  11.    transceiver options (e.g. "-TPO")
  12.  
  13.    Instructions are at
  14.     http://www.scyld.com/diag/index.html
  15.  
  16.     This software may be used and distributed according to the terms of
  17.     the GNU General Public License (GPL), incorporated herein by reference.
  18.     Contact the author for use under other terms.
  19.  
  20.     This program must be compiled with "-O"!
  21.     See the bottom of this file for the suggested compile-command.
  22.  
  23.     The author may be reached as becker@scyld.com, or C/O
  24.      Scyld Computing Corporation
  25.      410 Severn Ave., Suite 210
  26.      Annapolis MD 21403
  27.  
  28.     Support and updates available at
  29.      http://www.scyld.com/diag/index.html
  30.  
  31.     References
  32.      The 3Com EtherLink III manual, available from 3Com
  33. */
  34.  
  35. static char *version_msg =
  36. "3c5x9setup.c:v1.00 6/19/2000 Donald Becker (becker@scyld.com)\n"
  37. " http://www.scyld.com/diag/index.html\n";
  38. static char *usage_msg =
  39. "Usage: 3c5x9setup [-aEfFsvVw] [-p <IOport>] [-F 10baseT|10base2|AUI>] [-Q <IRQ>]\n";
  40.  
  41. #if ! defined(__OPTIMIZE__)
  42. #warning  You must compile this program with the correct options!
  43. #warning  See the last lines of the source file.
  44. #error You must compile this driver with "-O".
  45. #endif
  46. #include <unistd.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <getopt.h>
  50. #include <string.h>
  51. #include <errno.h>
  52.  
  53. #if defined(__linux__)  &&  __GNU_LIBRARY__ == 1
  54. #include <asm/io.h>            /* Newer libraries use <sys/io.h> instead. */
  55. #else
  56. #include <sys/io.h>
  57. /* Use   extern iopl(int level);  if your glibc does not define it. */
  58. #endif
  59.  
  60. /* We should use __u8 .. __u32, but they are not always defined. */
  61. typedef unsigned int u32;
  62. typedef unsigned short u16;
  63. typedef unsigned char u8;
  64.  
  65. struct option longopts[] = {
  66.  /* { name  has_arg  *flag  val } */
  67.     {"base-address", 1, 0, 'p'},
  68.     {"new-base-address", 1, 0, 'P'},
  69.     {"show-all-registers",    0, 0, 'a'},    /* Print all registers. */
  70.     {"debug",            0, 0, 'D'},
  71.     {"show-eeprom",        0, 0, 'e'}, /* Dump EEPROM contents (-ee valid). */
  72.     {"help",            0, 0, 'h'},    /* Give help */
  73.     {"emergency-rewrite",  0, 0, 'E'}, /* Re-write a corrupted EEPROM.  */
  74.     {"force-detection", 0, 0, 'f'},
  75.     {"new-interface",    1, 0, 'F'},    /* New interface (built-in, AUI, etc.) */
  76.     {"new-hwaddr",        1, 0, 'H'},    /* Set a new hardware address. */
  77.     {"new-IOaddress",    1, 0, 'P'},    /* New base I/O address. */
  78.     {"new-irq",    1, 0, 'Q'},        /* New interrupt number */
  79.     {"verbose",    0, 0, 'v'},        /* Verbose mode */
  80.     {"version", 0, 0, 'V'},        /* Display version number */
  81.     {"write-EEPROM", 1, 0, 'w'},/* Actually write the EEPROM with new vals */
  82.     { 0, 0, 0, 0 }
  83. };
  84.  
  85. /* Offsets from base I/O address. */
  86. #define EL3_CMD 0x0e
  87. #define EL3_STATUS 0x0e
  88.  
  89. enum Window0 {
  90.     Wn0EepromCmd = 10,        /* Window 0: EEPROM command register. */
  91.     Wn0EepromData = 12,        /* Window 0: EEPROM results register. */
  92.     IntrStatus=0x0E,            /* Valid in all windows. */
  93. };
  94.  
  95. #define     EEPROM_READ 0x80
  96. #define     EEPROM_WRITE 0x40
  97. #define     EEPROM_ERASE 0xC0
  98. #define     EEPROM_EWENB 0x30        /* Enable erasing/writing for 10 msec. */
  99. #define     EEPROM_EWDIS 0x00        /* Enable erasing/writing for 10 msec. */
  100. enum Win0_EEPROM_bits {
  101.     EEPROM_Read = 0x80, EEPROM_Busy = 0x8000,
  102. };
  103.  
  104. #define EL3WINDOW(win_num) outw(0x0800+(win_num), ioaddr + EL3_CMD)
  105.  
  106. /* Register window 1 offsets, the window used in normal operation. */
  107. enum Window1 {
  108.     TX_FIFO = 0x0,  RX_FIFO = 0x0,  Wn1RxErrors = 0x4,
  109.     Wn1RxStatus = 0x8,  Wn1Timer=0xA, Wn1TxStatus = 0xB,
  110.     Wn1TxFree = 0xC, /* Remaining free bytes in Tx buffer. */
  111. };
  112.  
  113. const char *intr_names[13] ={
  114.     "Interrupt latch", "Adapter Failure", "Tx Complete", "Tx Available",
  115.     "Rx Complete", "Rx Early Notice", "Driver Intr Request",
  116.     "Statistics Full", "DMA Done", "Download Complete", "Upload Complete",
  117.     "DMA in Progress", "Command in Progress",
  118. };
  119.  
  120. /* EEPROM operation locations. */
  121. enum eeprom_offset {
  122.     PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
  123.     EtherLink3ID=7, IFXcvrIO=8, IRQLine=9,
  124.     AltPhysAddr01=10, AltPhysAddr23=11, AltPhysAddr45=12,
  125.     DriverTune=13, Checksum=15};
  126.  
  127. /* Last-hope recovery major boo-boos: rewrite the EEPROM with the values
  128.    from my card (and hope I don't met you on the net...).
  129.    This image is valid only for an pre-B 3c509.
  130. */
  131. unsigned short djb_eeprom[16] = {
  132.     0x0020, 0xaf0e, 0x3bc2, 0x9058, 0xbc4e, 0x0036, 0x4441, 0x6d50,
  133.     0x0090, 0xaf00, 0x0020, 0xaf0e, 0x3bc2, 0x1310, 0x0000, 0x343c, }; 
  134. /* Values read from the EEPROM, and the new image. */
  135. #define EEPROM_SPACE 64
  136. unsigned short eeprom_contents[EEPROM_SPACE];
  137. unsigned short new_ee_contents[EEPROM_SPACE];
  138.  
  139. int verbose = 1, opt_f = 0, debug = 0;
  140. int show_regs = 0, show_eeprom = 0;
  141. int do_write_eeprom = 0;
  142. int ioaddr;
  143. static unsigned char new_hwaddr[6], set_hwaddr = 0;
  144.  
  145. const char *intrs_pending_msg = 
  146. " This network adapter has unhandled interrupts!\n"
  147. " This should never occur with properly configured adapter.  You may have\n"
  148. "   a hardware interrupt conflict.\n"
  149. " Check /proc/interrupts to verify that the interrupt is properly\n"
  150. "   registered, and that the count is increasing.\n"
  151. " This problem is frequently solved by moving the adapter to different IRQ.\n"
  152. " For ISA cards, verify that the BIOS setup has assigned the IRQ line to\n"
  153. "  ISA bus.\n"
  154. " For PCMCIA cards, change the configuration file, typically named\n"
  155. "  /etc/pcmcia/config.opts, to use a different IRQ.\n";
  156.  
  157. static void print_eeprom(unsigned short *eeprom_contents);
  158. static void write_eeprom(short ioaddr, int index, int value);
  159. static unsigned int calculate_checksum(unsigned short *values);
  160. static int do_update(unsigned short *ee_values,
  161.                      int index, char *field_name, int new_value);
  162.  
  163. int
  164. main(int argc, char **argv)
  165. {
  166.     int port_base = 0x300;
  167.     int new_interface = -1, new_irq = -1, new_ioaddr = -1;
  168.     int errflag = 0, show_version = 0;
  169.     int emergency_rewrite = 0;
  170.     int show_regs = 0, opt_a = 0;
  171.     int c, longind, i, j, saved_window;
  172.     extern char *optarg;
  173.  
  174.     while ((c = getopt_long(argc, argv, "aDeEfF:hi:p:P:Q:svVwX:",
  175.                             longopts, &longind))
  176.            != -1)
  177.         switch (c) {
  178.         case 'a': show_regs++; opt_a++;        break;
  179.         case 'D': debug++;                break;
  180.         case 'e': show_eeprom++;        break;
  181.         case 'E': emergency_rewrite++;    break;
  182.         case 'f': opt_f++;                break;
  183.         case 'F': case 'X':
  184.             if (strncmp(optarg, "10base", 6) == 0) {
  185.                 switch (optarg[6]) {
  186.                 case 'T':  new_interface = 0; break;
  187.                 case '2':  new_interface = 3; break;
  188.                 case '5':  new_interface = 1; break;
  189.                 default: errflag++;
  190.                 }
  191.             } else if (strcmp(optarg, "AUI") == 0)
  192.                 new_interface = 1;
  193.             else if (optarg[0] >= '0' &&  optarg[0] <= '3'
  194.                        &&  optarg[1] == 0)
  195.                 new_interface = optarg[0] - '0';
  196.             else {
  197.                 fprintf(stderr, "Invalid interface specified: it must be"
  198.                         " 0..3, '10base{T,2,5}' or 'AUI'.\n");
  199.                 errflag++;
  200.             }
  201.             break;
  202.         case 'H':
  203.             {
  204.                 int hwaddr[6], i;
  205.                 if (sscanf(optarg, "%2x:%2x:%2x:%2x:%2x:%2x",
  206.                            hwaddr, hwaddr + 1, hwaddr + 2,
  207.                            hwaddr + 3, hwaddr + 4, hwaddr + 5) == 6) {
  208.                     for (i = 0; i < 6; i++)
  209.                         new_hwaddr[i] = hwaddr[i];
  210.                     set_hwaddr++;
  211.                 } else
  212.                     errflag++;
  213.                 break;
  214.             }
  215.         case 'Q':
  216.             new_irq = atoi(optarg);
  217.             if (new_irq < 3 || new_irq > 15 || new_irq == 6 || new_irq == 8) {
  218.                 fprintf(stderr, "Invalid new IRQ %#x.  Valid values: "
  219.                         "3-5,7,9-15.\n", new_irq);
  220.                 errflag++;
  221.             }
  222.             break;
  223.         case 'p':
  224.             port_base = strtol(optarg, NULL, 16);
  225.             break;
  226.         case 'P':
  227.             new_ioaddr = strtol(optarg, NULL, 16);
  228.             if (new_ioaddr < 0x200 || new_ioaddr > 0x3f0) {
  229.                 fprintf(stderr, "Invalid new I/O address %#x.  Valid range "
  230.                         "0x200-0x3f0.\n", new_ioaddr);
  231.                 errflag++;
  232.             }
  233.             break;
  234.         case 'v': verbose++;        break;
  235.         case 'V': show_version++;    break;
  236.         case 'w': do_write_eeprom++;    break;
  237.         case '?': case 'h':
  238.             errflag++;
  239.         }
  240.     if (errflag) {
  241.         fprintf(stderr, usage_msg);
  242.         return 3;
  243.     }
  244.  
  245.     if (verbose || show_version)
  246.         printf(version_msg);
  247.  
  248.     if (ioperm(port_base, 16, 1) < 0) {
  249.         perror("3c5x9setup: ioperm()");
  250.         fprintf(stderr, "This program must be run as root.\n");
  251.         return 2;
  252.     }
  253.  
  254.     ioaddr = port_base;
  255.  
  256.     saved_window = inw(ioaddr + EL3_STATUS);
  257.     if (saved_window == 0xffff) {
  258.         printf("No EtherLink III device exists at address 0x%X.\n", ioaddr);
  259.         if ( ! opt_f) {
  260.             printf("Use the '-f' option proceed anyway.\n");
  261.             return 2;
  262.         }
  263.     }
  264.  
  265.     /* We can check for a stuck interrupt even while the chip is active. */
  266.     if (verbose || opt_a) {
  267.         unsigned intr_status = inw(ioaddr + IntrStatus);
  268.         printf(" %snterrupt sources are pending.\n",
  269.                (intr_status & 0x03ff) ? "I": "No i");
  270.         if (intr_status & 0x3ff) {
  271.             for (i = 0; i < 13; i++)
  272.                 if (intr_status & (1<<i))
  273.                     printf("   %s indication.\n", intr_names[i]);
  274.         }
  275.     }
  276.     if (!opt_f  && (saved_window & 0xe000) == 0x2000) {
  277.         int last_intr = inb(ioaddr + Wn1Timer);
  278.         printf("A potential 3c5*9 has been found, but it appears to still be "
  279.                "active.\nOnly limited information is available without "
  280.                "disturbing network operation.\n"
  281.                " Either shutdown the network, or use the '-f' flag to see all "
  282.                "registers.\n");
  283.         printf("  Available Tx room %d bytes, Tx/Rx Status %4.4x / %4.4x.\n",
  284.                inw(ioaddr + Wn1TxFree), inb(ioaddr + Wn1TxStatus),
  285.                inb(ioaddr + Wn1RxStatus));
  286.         if (last_intr != 255)
  287.             printf("  An interrupt occured only %d ticks ago!\n", last_intr);
  288.         if (saved_window & 0x00ff)
  289.             printf(intrs_pending_msg);
  290.         return 1;
  291.     }
  292.  
  293.     EL3WINDOW(0);
  294.     if (inw(port_base) == 0x6d50) {
  295.         printf("3c5x9 found at %#3.3x.\n", port_base);
  296.     } else {
  297.         printf("3c5*9 not found at %#3.3x, status %4.4x.\n"
  298.                "If there is a 3c5*9 card in the machine, explicitly set the"
  299.                " I/O port address\n  using '-p <ioaddr>\n",
  300.                port_base, inw(port_base));
  301.         if (opt_f < 2)
  302.             return 1;
  303.     }
  304.  
  305.     EL3WINDOW(5);
  306.     printf(" Indication enable is %4.4x, interrupt enable is %4.4x.\n",
  307.            inw(ioaddr + 12), inw(ioaddr + 10));
  308.  
  309.     if (show_regs) {
  310.         const char *statname[12] = {
  311.             "Carrier Lost", "Heartbeat", "Tx Multiple collisions",
  312.             "Tx Single collisions", "Tx Late collisions", "Rx FIFO overruns",
  313.             "Tx packets", "Rx packets", "Tx deferrals",
  314.             "(256 Rx/Tx counts)", "Rx bytes", "Tx bytes"};
  315.         int stats[12];
  316.         /* First read the statistics registers, which are clear-on-read. */
  317.         EL3WINDOW(6);
  318.         for (i = 0; i < 10; i++)
  319.             stats[i] = inb(ioaddr + i);
  320.         stats[10] = inw(ioaddr + 10);
  321.         stats[11] = inw(ioaddr + 12);
  322.         for (i = 0; i < 12; i++)
  323.             if (stats[i])
  324.                 printf("  Event counts: %s is %d.\n", statname[i], stats[i]);
  325.     }
  326.                         
  327.     if (show_regs) {
  328.         for (j = 0; j < 8; j++) {
  329.             int i;
  330.             printf("  Window %d:", j);
  331.             outw(0x0800 + j, ioaddr + 0x0e);
  332.             for (i = 0; i < 16; i+=2)
  333.                 printf(" %4.4x", inw(ioaddr + i));
  334.             printf(".\n");
  335.         }
  336.     }
  337.  
  338.     EL3WINDOW(0);
  339.  
  340.     /* Read the EEPROM. */
  341.     for (i = 0; i < EEPROM_SPACE; i++) {
  342.         int boguscheck;
  343.         outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
  344.         /* Pause for up to 162 us. for the read to take place.
  345.            Typical max. 175 ticks. */
  346.         for (boguscheck = 0; boguscheck < 1620; boguscheck++)
  347.             if ((inw(ioaddr + Wn0EepromCmd) & EEPROM_Busy) == 0)
  348.                 break;
  349.         eeprom_contents[i] = inw(ioaddr + Wn0EepromData);
  350.         if (show_eeprom > 2)
  351.             printf("EEPROM read of index %d %s after %d ticks -> %4.4x.\n",
  352.                    i, boguscheck < 1620 ? "completed" : "failed", boguscheck,
  353.                    eeprom_contents[i]);
  354.     }
  355.  
  356.     if (emergency_rewrite) {
  357.         if (emergency_rewrite < 3  ||  !do_write_eeprom)
  358.             printf(" Caution!  Last-chance EEPROM write requested.  The\n"
  359.                    " new EEPROM values will not be written without"
  360.                    " '-E -E -E -w' flags.\n");
  361.         else {
  362.             for (i = 0; i < 16; i++) {
  363.                 eeprom_contents[i] = djb_eeprom[i];
  364.                 write_eeprom(ioaddr, i, eeprom_contents[i]);
  365.             }
  366.         }
  367.     }
  368.     {
  369.         unsigned short new_ifxcvrio = eeprom_contents[IFXcvrIO];
  370.         unsigned short new_irqline = eeprom_contents[IRQLine];
  371.         int something_changed = 0;
  372.  
  373.         if (new_interface >= 0)
  374.             new_ifxcvrio = (new_interface << 14) | (new_ifxcvrio & 0x3fff);
  375.         if (new_ioaddr > 0)
  376.             new_ifxcvrio = ((new_ioaddr>>4) & 0x1f) | (new_ifxcvrio & 0xffe0);
  377.         if (new_irq > 0)
  378.             new_irqline = (new_irq << 12) | 0x0f00;
  379.  
  380.         if (do_update(eeprom_contents, IRQLine, "IRQ", new_irqline))
  381.             something_changed++;
  382.  
  383.         if (do_update(eeprom_contents, IFXcvrIO, "transceiver/IO",
  384.                       new_ifxcvrio))
  385.             something_changed++;
  386.  
  387.         /* To change another EEPROM value write it here. */
  388.  
  389.         if (do_update(eeprom_contents, Checksum, "checksum",
  390.                       calculate_checksum(eeprom_contents)))
  391.             something_changed++;
  392.  
  393.         if (something_changed  &&  !do_write_eeprom)
  394.             printf(" (The new EEPROM values will not be written without"
  395.                     " the '-w' flag.)\n");
  396.     }
  397.  
  398.     if (verbose > 1 || show_eeprom) {
  399.         print_eeprom(eeprom_contents);
  400.     }
  401.  
  402.     EL3WINDOW(saved_window>>13);
  403.  
  404.     return 0;
  405. }
  406.  
  407. static void print_eeprom(unsigned short *eeprom_contents)
  408. {
  409.     char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
  410.     u8 *p = (void *)eeprom_contents;
  411.     u16 *ee = eeprom_contents;
  412.     int i;
  413.  
  414.     printf(" EEPROM contents:");
  415.     if (show_eeprom)
  416.         for(i = 0; i < EEPROM_SPACE; i++)
  417.             printf("%s %4.4x", i % 8 ? "" : "\n   ", eeprom_contents[i]);
  418.     printf("\n  Model number 3c%2.2x%1.1x version %1.1x, base I/O %#x, IRQ %d, "
  419.            "%s port.\n",
  420.            eeprom_contents[ModelID] & 0x00ff,
  421.            eeprom_contents[ModelID] >> 12,
  422.            (eeprom_contents[ModelID] >> 8) & 0x000f,
  423.            0x200 + ((eeprom_contents[IFXcvrIO] & 0x1f) << 4),
  424.            eeprom_contents[IRQLine] >> 12,
  425.            if_names[eeprom_contents[IFXcvrIO] >> 14]);
  426.  
  427.     p = (unsigned char *)(eeprom_contents + PhysAddr01);
  428.     printf("  3Com Node Address ");
  429.     for (i = 0; i < 5; i++)
  430.         printf("%2.2X:", p[i^1]);
  431.     printf("%2.2X (used as a unique ID only).\n"
  432.            "  OEM Station address ",
  433.            p[i^1]);
  434.     for (i = 20; i < 25; i++)
  435.         printf("%2.2X:", p[i ^ 1]);
  436.     printf("%2.2X (used as the ethernet address).\n", p[24]);
  437.  
  438.     /* Y2K safe.  This two-digit date is for information purposes only.
  439.        It is never used for computations. */
  440.     printf("  Manufacture date (MM/DD/YY) %d/%d/%d, division %c,"
  441.            " product %c%c.\n", (ee[4] >> 5) & 15,
  442.            ee[4] & 31, ee[4] >> 9, p[10], p[12], p[13]);
  443.     printf("  Options: %s duplex, %sable linkbeat.\n",
  444.            ee[13] & 0x8000 ? "force full" : "half",
  445.            ee[13] & 0x4000 ? "dis" : "en");
  446.  
  447.     if (calculate_checksum(eeprom_contents) != eeprom_contents[Checksum])
  448.         printf("****CHECKSUM ERROR****: Calcuated checksum: %4.4x, "
  449.                "stored checksum %4.4x.\n",
  450.                calculate_checksum(eeprom_contents),
  451.                eeprom_contents[Checksum]);
  452.     else
  453.         printf("  The computed checksum matches the stored checksum of %4.4x.\n",
  454.                eeprom_contents[Checksum]);
  455. }
  456.  
  457.  
  458. static void write_eeprom(short ioaddr, int index, int value)
  459. {
  460.     int timer;
  461.     /* Verify that the EEPROM is idle. */
  462.     for (timer = 1620; inw(ioaddr + Wn0EepromCmd) & 0x8000;)
  463.         if (--timer < 0)
  464.             goto error_return;
  465.     outw(EEPROM_EWENB, ioaddr + Wn0EepromCmd);
  466.     usleep(60);
  467.     outw(EEPROM_ERASE + index, ioaddr + Wn0EepromCmd);
  468.     usleep(60);
  469.     outw(EEPROM_EWENB, ioaddr + Wn0EepromCmd);
  470.     usleep(60);
  471.     outw(value, ioaddr + Wn0EepromData);
  472.     outw(EEPROM_WRITE + index, ioaddr + Wn0EepromCmd);
  473.     for (timer = 16000; inw(ioaddr + Wn0EepromCmd) & 0x8000;)
  474.         if (--timer < 0)
  475.             goto error_return;
  476.     if (debug)
  477.         fprintf(stderr, "EEPROM wrote index %d with 0x%4.4x after %d ticks!\n",
  478.                 index, value, 16000-timer);
  479.     return;
  480. error_return:
  481.     fprintf(stderr, "Failed to write EEPROM location %d with 0x%4.4x!\n",
  482.             index, value);
  483. }
  484.  
  485. /* Calculate the EEPROM checksum.
  486.    The checksum for the fixed values is returned in the high byte.
  487.    The checksum for the programmable variables is in the low the byte.
  488.    */
  489.  
  490. static unsigned int
  491. calculate_checksum(unsigned short *values)
  492. {
  493.     int fixed_checksum = 0, var_checksum = 0;
  494.     int i;
  495.  
  496.     for (i = 0; i <= 14; i++) {                /* Note: 14 (loc. 15 is the sum) */
  497.         if (i == IFXcvrIO || i == IRQLine || i == DriverTune)
  498.             var_checksum ^= values[i];
  499.         else
  500.             fixed_checksum ^= values[i];
  501.     }
  502.     return ((fixed_checksum ^ (fixed_checksum << 8)) & 0xff00) |
  503.         ((var_checksum ^ (var_checksum >> 8)) & 0xff);
  504. }
  505.  
  506. static int do_update(unsigned short *ee_values,
  507.                      int index, char *field_name, int new_value)
  508. {
  509.     if (ee_values[index] != new_value) {
  510.         if (do_write_eeprom) {
  511.             printf("Writing new %s entry 0x%4.4x.\n",
  512.                    field_name, new_value);
  513.             write_eeprom(ioaddr, index, new_value);
  514.         } else
  515.             printf(" Would write new %s entry 0x%4.4x (old value 0x%4.4x).\n",
  516.                    field_name, new_value, ee_values[index]);
  517.         ee_values[index] = new_value;
  518.         return 1;
  519.     }
  520.     return 0;
  521. }
  522.  
  523.  
  524. /*
  525.  * Local variables:
  526.  *  compile-command: "cc -O -Wall -o 3c5x9setup 3c5x9setup.c"
  527.  *  c-indent-level: 4
  528.  *  c-basic-offset: 4
  529.  *  tab-width: 4
  530.  * End:
  531.  */
  532.