[ LUGOS ] 3c509(8) Ethernet
Timotej Ecimovic
cic na latefibm1.fs.uni-lj.si
Sre Maj 21 17:05:59 CEST 1997
>
> > Zakaj hocete vsi 3Com kartice konfigurirati pod dosom?
> > Sej obstaja programcek '3c5x9' tut za Linux!
> >
> > feri.
>
> Kako pa se imenuje in ke so dobi ?
>
Tukaj imas. Pojma nimam kje sem jaz to staknil pred casom...
Cisto na dnu ti pise kako ga skompajlati.
Cic
---------------------------------------------
/* 3c5x9setup.c: Setup program for 3Com EtherLink III ethercards.
Copyright 1994-1996 by Donald Becker.
This version released under the Gnu Public Lincese, incorporated herein
by reference. Contact the author for use under other terms.
This is a EEPROM setup and diagnostic program for the 3Com 3c5x9 series
ethercards.
This program must be compiled with "-O"! See the bottom of this file
for the suggested compile-command.
The author may be reached as becker na cesdis.gsfc.nasa.gov.
C/O USRA-CESDIS, Code 930.5 Bldg. 28, Nimbus Rd., Greenbelt MD 20771
*/
static char *version_msg =
"3c5x9setup.c:v0.04 12/11/96 Donald Becker (becker na cesdis.gsfc.nasa.gov)\n";
static char *usage_msg =
"Usage: 3c5x9 [-aEfFsvVw] [-p <IOport>] [-F 10baseT|10base2|AUI>] [-Q <IRQ>]\n";
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <strings.h>
#include <linux/in.h>
#include <asm/io.h>
struct option longopts[] = {
/* { name has_arg *flag val } */
{"base-address", 1, 0, 'p'},
{"new-base-address", 1, 0, 'P'},
{"show_all_registers", 0, 0, 'a'}, /* Print all registers. */
{"help", 0, 0, 'h'}, /* Give help */
{"emergency-rewrite", 0, 0, 'E'}, /* Re-write a corrupted EEPROM. */
{"force-detection", 0, 0, 'f'},
{"new-interface", 1, 0, 'F'}, /* New interface (built-in, AUI, etc.) */
{"new-IOaddress", 1, 0, 'P'}, /* New base I/O address. */
{"new-irq", 1, 0, 'Q'}, /* New interrupt number */
{"verbose", 0, 0, 'v'}, /* Verbose mode */
{"version", 0, 0, 'V'}, /* Display version number */
{"write-EEPROM", 1, 0, 'w'},/* Actually write the EEPROM with new vals */
{ 0, 0, 0, 0 }
};
/* Offsets from base I/O address. */
#define EL3_DATA 0x00
#define EL3_CMD 0x0e
#define EL3_STATUS 0x0e
#define EEPROM_READ 0x80
#define EEPROM_WRITE 0x40
#define EEPROM_ERASE 0xC0
#define EEPROM_EWENB 0x30 /* Enable erasing/writing for 10 msec. */
#define EEPROM_EWDIS 0x00 /* Enable erasing/writing for 10 msec. */
#define EL3WINDOW(win_num) outw(0x0800+(win_num), ioaddr + EL3_CMD)
/* Register window 1 offsets, used in normal operation. */
#define TX_FREE 0x0C
#define TX_STATUS 0x0B
#define TX_FIFO 0x00
#define RX_FIFO 0x00
/* EEPROM operation locations. */
enum eeprom_offset {
PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
EtherLink3ID=7, IFXcvrIO=8, IRQLine=9,
AltPhysAddr01=10, AltPhysAddr23=11, AltPhysAddr45=12,
DriverTune=13, Checksum=15};
/* Last-hope recovery major boo-boos: rewrite the EEPROM with the values
from my card (and hope I don't met you on the net...). */
unsigned short djb_eeprom[16] = {
0x0020, 0xaf0e, 0x3bc2, 0x9058, 0xbc4e, 0x0036, 0x4441, 0x6d50,
0x0090, 0xaf00, 0x0020, 0xaf0e, 0x3bc2, 0x1310, 0x0000, 0x343c, };
/* Values read from the EEPROM, and the new image. */
unsigned short eeprom_contents[16];
unsigned short new_ee_contents[16];
int do_write_eeprom = 0;
int ioaddr;
static void print_eeprom(unsigned short *eeprom_contents);
static void write_eeprom(short ioaddr, int index, int value);
static unsigned int calculate_checksum(unsigned short *values);
static int do_update(unsigned short *ee_values,
int index, char *field_name, int new_value);
int
main(int argc, char **argv)
{
int port_base = 0x300;
int new_interface = -1, new_irq = -1, new_ioaddr = -1;
int errflag = 0, opt_f = 0, verbose = 0, show_version = 0;
int emergency_rewrite = 0;
int dump_all_regs = 0;
int c, longind, i, j, saved_window;
extern char *optarg;
while ((c = getopt_long(argc, argv, "aEfF:i:p:P:Q:svVw",
longopts, &longind))
!= -1)
switch (c) {
case 'a': dump_all_regs++; break;
case 'E': emergency_rewrite++; break;
case 'f': opt_f++; break;
case 'F':
if (strncmp(optarg, "10base", 6) == 0) {
switch (optarg[6]) {
case 'T': new_interface = 0; break;
case '2': new_interface = 3; break;
case '5': new_interface = 1; break;
default: errflag++;
}
} else if (strcmp(optarg, "AUI") == 0)
new_interface = 1;
else if (optarg[0] >= '0' && optarg[0] <= '3'
&& optarg[1] == 0)
new_interface = optarg[0] - '0';
else {
fprintf(stderr, "Invalid interface specified: it must be"
" 0..3, '10base{T,2,5}' or 'AUI'.\n");
errflag++;
}
break;
case 'Q':
new_irq = atoi(optarg);
if (new_irq < 3 || new_irq > 15 || new_irq == 6 || new_irq == 8) {
fprintf(stderr, "Invalid new IRQ %#x. Valid values: "
"3-5,7,9-15.\n", new_irq);
errflag++;
}
break;
case 'p':
port_base = strtol(optarg, NULL, 16);
break;
case 'P':
new_ioaddr = strtol(optarg, NULL, 16);
if (new_ioaddr < 0x200 || new_ioaddr > 0x3f0) {
fprintf(stderr, "Invalid new I/O address %#x. Valid range "
"0x200-0x3f0.\n", new_ioaddr);
errflag++;
}
break;
case 'v': verbose++; break;
case 'V': show_version++; break;
case 'w': do_write_eeprom++; break;
case '?':
errflag++;
}
if (errflag) {
fprintf(stderr, usage_msg);
return 3;
}
if (ioperm(port_base, 16, 1) < 0) {
perror("3c5x9setup: ioperm()");
fprintf(stderr, "This program must be run as root.\n");
return 2;
}
if (verbose)
printf(version_msg);
ioaddr = port_base;
saved_window = inw(ioaddr + EL3_STATUS);
if (!opt_f && (saved_window & 0xe000) == 0x2000) {
printf("A potential 3c5*9 has been found, but it appears to still "
"be active.\nEither shutdown the network, or use the"
" '-f' flag.\n");
return 1;
}
EL3WINDOW(0);
if (inw(port_base) == 0x6d50) {
printf("3c5x9 found at %#3.3x.\n", port_base);
} else {
printf("3c5*9 not found at %#3.3x, status %4.4x.\n"
"If there is a 3c5*9 card in the machine, explicitly set the"
" I/O port address\n using '-p <ioaddr>\n",
port_base, inw(port_base));
if (opt_f < 2)
return 1;
}
if (dump_all_regs) {
for (j = 0; j < 8; j++) {
int i;
printf("Window %d:", j);
outw(0x0800 + j, ioaddr + 0x0e);
for (i = 0; i < 16; i+=2)
printf(" %4.4x", inw(ioaddr + i));
printf(".\n");
}
}
EL3WINDOW(0);
/* Read the EEPROM. */
for (i = 0; i < 16; i++) {
outw(EEPROM_READ + i, ioaddr + 10);
/* Pause for at least 162 us. for the read to take place. */
usleep(162);
eeprom_contents[i] = inw(ioaddr + 12);
if (verbose)
printf("EEPROM index %d: %4.4x.\n", i, eeprom_contents[i]);
}
if (emergency_rewrite) {
if (emergency_rewrite < 3 || !do_write_eeprom)
printf(" Caution! Last-chance EEPROM write requested. The\n"
" new EEPROM values will not be written without"
" '-E -E -E -w' flags.\n");
else {
for (i = 0; i < 16; i++) {
eeprom_contents[i] = djb_eeprom[i];
write_eeprom(ioaddr, i, eeprom_contents[i]);
}
}
}
{
unsigned short new_ifxcvrio = eeprom_contents[IFXcvrIO];
unsigned short new_irqline = eeprom_contents[IRQLine];
int something_changed = 0;
if (new_interface >= 0)
new_ifxcvrio = (new_interface << 14) | (new_ifxcvrio & 0x3fff);
if (new_ioaddr > 0)
new_ifxcvrio = ((new_ioaddr>>4) & 0x1f) | (new_ifxcvrio & 0xffe0);
if (new_irq > 0)
new_irqline = (new_irq << 12) | 0x0f00;
if (do_update(eeprom_contents, IRQLine, "IRQ", new_irqline))
something_changed++;
if (do_update(eeprom_contents, IFXcvrIO, "transceiver/IO",
new_ifxcvrio))
something_changed++;
/* To change another EEPROM value write it here. */
if (do_update(eeprom_contents, Checksum, "checksum",
calculate_checksum(eeprom_contents)))
something_changed++;
if (something_changed && !do_write_eeprom)
printf(" (The new EEPROM values will not be written without"
" the '-w' flag.)\n");
}
print_eeprom(eeprom_contents);
EL3WINDOW(saved_window>>13);
return 0;
}
static void print_eeprom(unsigned short *eeprom_contents)
{
unsigned char *phys_addr;
char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
int i;
printf("Model number 3c%2.2x%1.1x version %1.1x, base I/O %#x,"
" IRQ %d, %s port.\n",
eeprom_contents[ModelID] & 0x00ff,
eeprom_contents[ModelID] >> 12,
(eeprom_contents[ModelID] >> 8) & 0x000f,
0x200 + ((eeprom_contents[IFXcvrIO] & 0x1f) << 4),
eeprom_contents[IRQLine] >> 12,
if_names[eeprom_contents[IFXcvrIO] >> 14]);
phys_addr = (unsigned char *)(eeprom_contents + PhysAddr01);
printf("Primary physical address is %2.2x", phys_addr[1]);
for (i = 1; i < 6; i++)
printf(":%2.2x", phys_addr[i^1]);
phys_addr = (unsigned char *)(eeprom_contents + AltPhysAddr01);
printf("\nAlternate physical address is %2.2x", phys_addr[1]);
for (i = 1; i < 6; i++)
printf(":%2.2x", phys_addr[i^1]);
printf("\n");
if (calculate_checksum(eeprom_contents) != eeprom_contents[Checksum])
printf("****CHECKSUM ERROR****: Calcuated checksum: %4.4x, "
"stored checksum %4.4x.\n",
calculate_checksum(eeprom_contents),
eeprom_contents[Checksum]);
}
static void write_eeprom(short ioaddr, int index, int value)
{
outw(value, ioaddr + 12);
outw(EEPROM_EWENB, ioaddr + 10);
usleep(60);
outw(EEPROM_ERASE + index, ioaddr + 10);
usleep(60);
outw(EEPROM_EWENB, ioaddr + 10);
usleep(60);
outw(value, ioaddr + 12);
outw(EEPROM_WRITE + index, ioaddr + 10);
usleep(10000);
}
/* Calculate the EEPROM checksum.
The checksum for the fixed values is returned in the high byte.
The checksum for the programmable variables is in the low the byte.
*/
static unsigned int
calculate_checksum(unsigned short *values)
{
int fixed_checksum = 0, var_checksum = 0;
int i;
for (i = 0; i <= 14; i++) { /* Note: 14 (loc. 15 is the sum) */
if (i == IFXcvrIO || i == IRQLine || i == DriverTune)
var_checksum ^= values[i];
else
fixed_checksum ^= values[i];
}
return ((fixed_checksum ^ (fixed_checksum << 8)) & 0xff00) |
((var_checksum ^ (var_checksum >> 8)) & 0xff);
}
static int do_update(unsigned short *ee_values,
int index, char *field_name, int new_value)
{
if (ee_values[index] != new_value) {
if (do_write_eeprom) {
printf("Writing new %s entry 0x%4.4x.\n",
field_name, new_value);
write_eeprom(ioaddr, index, new_value);
} else
printf(" Would write new %s entry 0x%4.4x (old value 0x%4.4x).\n",
field_name, new_value, ee_values[index]);
ee_values[index] = new_value;
return 1;
}
return 0;
}
/*
* Local variables:
* compile-command: "cc -N -O -Wall -o 3c5x9 3c5x9setup.c"
* tab-width: 4
* c-indent-level: 4
* End:
*/
Dodatne informacije o seznamu Starilist