Browse Source

[3c90xutil] Update bromutil.c and cromutil.c.

bromutil.c has been updated with a command to "fix" 3c905B NICs
so that EEPROMs larger than 8K may be used.

cromutil.c has been replaced with an updated version that has been
included in etherboot-5.4 for some time now.

See README for usage.

Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0-rc1
Thomas Miletich 14 years ago
parent
commit
90bffed805

+ 1
- 1
contrib/3c90xutil/Makefile View File

@@ -1,4 +1,4 @@
1
-FILES = cromutil bromutil
1
+FILES = cromutil ocromutil bromutil
2 2
 
3 3
 INCLUDEDIR = /usr/include
4 4
 CFLAGS = -O2 -fomit-frame-pointer -Wall -I$(INCLUDEDIR)

+ 49
- 0
contrib/3c90xutil/README View File

@@ -8,6 +8,55 @@ with AT49BV512 Flash memory, and created cromutil and bromutil to
8 8
 differentiate the versions.  cromutil is for 3C905C and bromutil is
9 9
 for 3C905B.
10 10
 
11
+8.28.2005 I am adding a new version from Jorge L. deLyra that will
12
+replace cromutil.c.  I will rename cromutil.c to ocromutil.c
13
+
14
+  From:	        delyra@fma.if.usp.br
15
+  Subject:	Improved version of cromutil.c.
16
+  Date:		June 22, 2004 12:19:00 AM EDT
17
+  To:		mdc@thinguin.org
18
+
19
+  Dear Marty,
20
+
21
+       Below you will find a new version of the cronutil.c program. Since
22
+  the changes were quite large I am sending the program rather than a patch.
23
+  I added support for 3C905CX cards with a page-mode super-flash EEPROM, and
24
+  included several informative messages, a programming progress report and a
25
+  detailed help message. I did all the tests I could with it and it seems to
26
+  work correctly for the 3C905CX with either type of EEPROM chip.
27
+
28
+  A question: is there a similar program for Intel eepro100 cards or for the
29
+  Intel or 3COM Gbit cards?
30
+					  Cheers,
31
+
32
+  ----------------------------------------------------------------
33
+	  Jorge L. deLyra,  Associate Professor of Physics
34
+	      The University of Sao Paulo,  IFUSP-DFMA
35
+	 For more information: finger delyra@latt.if.usp.br
36
+  ----------------------------------------------------------------
37
+
38
+12/4/2009 The new cromutil version from Jorge L. deLyra can be found in
39
+cromutil.c, whereas the old version can be found in ocromutil.c.
40
+
41
+bromutil.c now supports enabling a bootrom workaround that was previously
42
+implemented in the old 3c90x driver. Some 3c90xB cards refuse to load gPXE
43
+after the ROM is burned. The gPXE banner is likely to appear, but gPXE will
44
+crash soon after.
45
+If this is the case try the following commands. It is assumed that you replace
46
+0x6600 with the I/O address of your card which can be acquired with:
47
+(look for a line like 'I/O ports at e400')
48
+ $ lspci -v
49
+
50
+    $ make
51
+    $ ./bromutil 0x6600 bootrom
52
+
53
+This command will write into the settings EEPROM of the network card. In case
54
+the network card shows any unexpected behavior it is possible to restore the
55
+EEPROM settings with a 3COm provided tool called '3c90xcfg.exe'(google it for
56
+mirrors).
57
+
58
+  -- Thomas Miletich
59
+
11 60
 Be careful. You can easily erase your Flash memory using these
12 61
 utilities.  Make *sure* to back them up first using the "read"
13 62
 command. You must "erase" before using "prog" to program the chip with

+ 213
- 128
contrib/3c90xutil/bromutil.c View File

@@ -10,6 +10,7 @@
10 10
 #include <stdio.h>
11 11
 #include <stdlib.h>
12 12
 #include <unistd.h>
13
+#include <string.h>
13 14
 
14 15
 #ifdef __FreeBSD__
15 16
 
@@ -30,140 +31,224 @@
30 31
 
31 32
 #endif
32 33
 
33
-int main(int argc, char **argv)
34
-{
35
-    unsigned int i, j, n;
36
-    unsigned int ioaddr;
37
-    unsigned long recvrstat;
38
-    unsigned char buf[128];
39
-    unsigned char b;
34
+/*
35
+ * write_eeprom() and enum definitions are copied from vortex-diag.c,
36
+ * Copyright 1997-2004 by Donald Becker.
37
+ *	This software may be used and distributed according to the terms of
38
+ *	the GNU General Public License (GPL), incorporated herein by reference.
39
+ *	Contact the author for use under other terms.
40
+ */
40 41
 
41
-    if (argc != 3) {
42
-      printf("Usage: romid ioaddr [erase|protect|unprotect|id|read >file|prog <file]\n");
43
-      exit(-1);
44
-    }
42
+enum vortex_cmd {
43
+	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
44
+	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
45
+	UpStall = 6<<11, UpUnstall = (6<<11)+1,
46
+	DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
47
+	RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
48
+	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
49
+	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
50
+	SetTxThreshold = 18<<11, SetTxStart = 19<<11,
51
+	StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
52
+	StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,
53
+};
54
+
55
+enum Window0 {
56
+	Wn0EepromCmd = 10,		/* Window 0: EEPROM command register. */
57
+	Wn0EepromData = 12,		/* Window 0: EEPROM results register. */
58
+	IntrStatus=0x0E,		/* Valid in all windows. */
59
+};
60
+
61
+enum Win0_EEPROM_cmds {
62
+	EEPROM_Read = 2, EEPROM_WRITE = 1, EEPROM_ERASE = 3,
63
+	EEPROM_EWENB = 0xC,		/* Enable erasing/writing for 10 msec. */
64
+	EEPROM_EWDIS = 0x0,		/* Disable EWENB before 10 msec timeout. */
65
+};
66
+
67
+#define debug 1
68
+static void write_eeprom(long ioaddr, int addrlen, int index, int value)
69
+{
70
+	int timer;
71
+
72
+	/* Verify that the EEPROM is idle. */
73
+	for (timer = 1620; inw(ioaddr + Wn0EepromCmd) & 0x8000;)
74
+		if (--timer < 0)
75
+			goto error_return;
76
+	/* Enable writing: EEPROM_EWENB | 110000.... */
77
+	OUTW(3 << (addrlen-2), ioaddr + Wn0EepromCmd);
78
+	for (timer = 400; inw(ioaddr + Wn0EepromCmd) & 0x8000;) {
79
+		if (--timer < 0)
80
+			goto error_return;
81
+	}
82
+	if (debug)
83
+		fprintf(stderr, "EEPROM write enable took %d ticks!\n", 400 - timer);
84
+	OUTW((EEPROM_ERASE << addrlen) + index, ioaddr + Wn0EepromCmd);
85
+	for (timer = 16000; inw(ioaddr + Wn0EepromCmd) & 0x8000;)
86
+		if (--timer < 0) {
87
+			fprintf(stderr, "EEPROM failed to erase index %d!\n", index);
88
+			return;
89
+		}
90
+	if (debug)
91
+		fprintf(stderr, "EEPROM erased index %d after %d ticks!\n",
92
+				index, 16000-timer);
93
+	OUTW(3 << (addrlen-2), ioaddr + Wn0EepromCmd);
94
+	for (timer = 400; inw(ioaddr + Wn0EepromCmd) & 0x8000;) {
95
+		if (--timer < 0)
96
+			goto error_return;
97
+	}
98
+	if (debug)
99
+		fprintf(stderr, "EEPROM write enable took %d ticks!\n", 400-timer);
100
+	OUTW(value, ioaddr + Wn0EepromData);
101
+	OUTW((EEPROM_WRITE << addrlen) + index, ioaddr + Wn0EepromCmd);
102
+	for (timer = 16000; inw(ioaddr + Wn0EepromCmd) & 0x8000;)
103
+		if (--timer < 0)
104
+			goto error_return;
105
+	if (debug)
106
+		fprintf(stderr, "EEPROM wrote index %d with 0x%4.4x after %d ticks!\n",
107
+				index, value, 16000-timer);
108
+	return;
109
+error_return:
110
+	fprintf(stderr, "Failed to write EEPROM location %d with 0x%4.4x!\n",
111
+			index, value);
112
+}
45 113
 
114
+int main(int argc, char **argv)
115
+{
116
+	unsigned int i, j, n;
117
+	unsigned int ioaddr;
118
+	unsigned long recvrstat;
119
+	unsigned char buf[128];
120
+	unsigned char b;
121
+
122
+	if (argc != 3) {
123
+		printf
124
+		    ("Usage: romid ioaddr [erase|protect|unprotect|id|bootrom|read >file|prog <file]\n");
125
+		exit(-1);
126
+	}
46 127
 #ifdef __FreeBSD__
47
-    /* get permissions for in/out{blw} */
48
-    open("/dev/io",O_RDONLY,0);
128
+	/* get permissions for in/out{blw} */
129
+	open("/dev/io", O_RDONLY, 0);
49 130
 #else
50
-    setuid(0); /* if we're setuid, do it really */
51
-    if (iopl(3)) {
52
-      perror("iopl()");
53
-      exit(1);
54
-    }
131
+	setuid(0);		/* if we're setuid, do it really */
132
+	if (iopl(3)) {
133
+		perror("iopl()");
134
+		exit(1);
135
+	}
55 136
 #endif
56 137
 
57
-    sscanf(argv[1],"%x",&ioaddr);
58
-    /* Set the register window to 3 for the 3c905b */
59
-    OUTW(0x803, ioaddr+0xe);
60
-    recvrstat = inl(ioaddr);	/* save the receiver status */
61
-    /* set the receiver type to MII so the full bios rom address space
62
-       can be accessed */
63
-    OUTL((recvrstat & 0xf00fffff)|0x00600000, ioaddr);
64
-
65
-    /* Set the register window to 0 for the 3c905b */
66
-    OUTW(0x800, ioaddr+0xe);
67
-
68
-    if (strcmp(argv[2], "erase") == 0) {
69
-      /* do the funky chicken to erase the rom contents */
70
-      OUTL(0x5555, ioaddr+0x4);
71
-      OUTB(0xaa, ioaddr+0x8);
72
-      OUTL(0x2aaa, ioaddr+0x4);
73
-      OUTB(0x55, ioaddr+0x8);
74
-      OUTL(0x5555, ioaddr+0x4);
75
-      OUTB(0x80, ioaddr+0x8);
76
-      OUTL(0x5555, ioaddr+0x4);
77
-      OUTB(0xaa, ioaddr+0x8);
78
-      OUTL(0x2aaa, ioaddr+0x4);
79
-      OUTB(0x55, ioaddr+0x8);
80
-      OUTL(0x5555, ioaddr+0x4);
81
-      OUTB(0x10, ioaddr+0x8);
82
-      printf("Bios ROM at %04x has been erased\n", ioaddr);
83
-    } else if (strcmp(argv[2], "protect") == 0) {
84
-      OUTL(0x5555, ioaddr+0x4);
85
-      OUTB(0xaa, ioaddr+0x8);
86
-      OUTL(0x2aaa, ioaddr+0x4);
87
-      OUTB(0x55, ioaddr+0x8);
88
-      OUTL(0x5555, ioaddr+0x4);
89
-      OUTB(0xa0, ioaddr+0x8);
90
-      printf("Software Data Protection for Bios ROM at %04x has been enabled\n",
91
-	     ioaddr);
92
-    } else if (strcmp(argv[2], "unprotect") == 0) {
93
-      OUTL(0x5555, ioaddr+0x4);
94
-      OUTB(0xaa, ioaddr+0x8);
95
-      OUTL(0x2aaa, ioaddr+0x4);
96
-      OUTB(0x55, ioaddr+0x8);
97
-      OUTL(0x5555, ioaddr+0x4);
98
-      OUTB(0x80, ioaddr+0x8);
99
-      OUTL(0x5555, ioaddr+0x4);
100
-      OUTB(0xaa, ioaddr+0x8);
101
-      OUTL(0x2aaa, ioaddr+0x4);
102
-      OUTB(0x55, ioaddr+0x8);
103
-      OUTL(0x5555, ioaddr+0x4);
104
-      OUTB(0x20, ioaddr+0x8);
105
-      printf("Software Data Protection for Bios ROM at %04x has been disabled\n",
106
-	     ioaddr);
107
-    } else if (strcmp(argv[2], "id") == 0) {
108
-      OUTL(0x5555, ioaddr+0x4);
109
-      OUTB(0xaa, ioaddr+0x8);
110
-      OUTL(0x2aaa, ioaddr+0x4);
111
-      OUTB(0x55, ioaddr+0x8);
112
-      OUTL(0x5555, ioaddr+0x4);
113
-      OUTB(0x90, ioaddr+0x8);
114
-      /* 10ms delay needed */
115
-      printf("Manufacturer ID - ");
116
-      /* manuf. id */
117
-      OUTL(0x0000, ioaddr+0x4);
118
-      printf("%02x\n", inb(ioaddr+0x8));
119
-      /* device id */
120
-      OUTL(0x0001, ioaddr+0x4);
121
-      printf("Device ID - %02x\n", inb(ioaddr+0x8));
122
-      /* undo the funky chicken */
123
-      OUTL(0x5555, ioaddr+0x4);
124
-      OUTB(0xaa, ioaddr+0x8);
125
-      OUTL(0x2aaa, ioaddr+0x4);
126
-      OUTB(0x55, ioaddr+0x8);
127
-      OUTL(0x5555, ioaddr+0x4);
128
-      OUTB(0xf0, ioaddr+0x8);
129
-    } else if (strcmp(argv[2], "read") == 0) {
130
-      for (i = 0; i < 65536; i++) {
131
-	OUTL(i, ioaddr+0x4);
132
-	b = inb(ioaddr+0x8);
133
-	write(1, &b, 1);
134
-      }
135
-    } else if (strcmp(argv[2], "prog") == 0) {
136
-      /* program the rom in 128 bute chunks */
137
-      for (i = 0, n = 0; i < 65536; i += n) {
138
-	n = read(0, buf, 128);
139
-	if (n == 0)
140
-	  break;
141
-	if (n < 0) {
142
-	  perror("File Error");
143
-	  exit(-3);
144
-	}
145
-	/* disable SDP temporarily for programming a sector */
146
-	OUTL(0x5555, ioaddr+0x4);
147
-	OUTB(0xaa, ioaddr+0x8);
148
-	OUTL(0x2aaa, ioaddr+0x4);
149
-	OUTB(0x55, ioaddr+0x8);
150
-	OUTL(0x5555, ioaddr+0x4);
151
-	OUTB(0xa0, ioaddr+0x8);
152
-	for (j = 0; j < n; j++) {
153
-	  OUTL(i+j, ioaddr+0x4);
154
-	  OUTB(buf[j], ioaddr+0x8);
138
+	sscanf(argv[1], "%x", &ioaddr);
139
+	/* Set the register window to 3 for the 3c905b */
140
+	OUTW(0x803, ioaddr + 0xe);
141
+	recvrstat = inl(ioaddr);	/* save the receiver status */
142
+	/* set the receiver type to MII so the full bios rom address space
143
+	   can be accessed */
144
+	OUTL((recvrstat & 0xf00fffff) | 0x00600000, ioaddr);
145
+
146
+	/* Set the register window to 0 for the 3c905b */
147
+	OUTW(0x800, ioaddr + 0xe);
148
+
149
+	if (strcmp(argv[2], "erase") == 0) {
150
+		/* do the funky chicken to erase the rom contents */
151
+		OUTL(0x5555, ioaddr + 0x4);
152
+		OUTB(0xaa, ioaddr + 0x8);
153
+		OUTL(0x2aaa, ioaddr + 0x4);
154
+		OUTB(0x55, ioaddr + 0x8);
155
+		OUTL(0x5555, ioaddr + 0x4);
156
+		OUTB(0x80, ioaddr + 0x8);
157
+		OUTL(0x5555, ioaddr + 0x4);
158
+		OUTB(0xaa, ioaddr + 0x8);
159
+		OUTL(0x2aaa, ioaddr + 0x4);
160
+		OUTB(0x55, ioaddr + 0x8);
161
+		OUTL(0x5555, ioaddr + 0x4);
162
+		OUTB(0x10, ioaddr + 0x8);
163
+		printf("Bios ROM at %04x has been erased\n", ioaddr);
164
+	} else if (strcmp(argv[2], "protect") == 0) {
165
+		OUTL(0x5555, ioaddr + 0x4);
166
+		OUTB(0xaa, ioaddr + 0x8);
167
+		OUTL(0x2aaa, ioaddr + 0x4);
168
+		OUTB(0x55, ioaddr + 0x8);
169
+		OUTL(0x5555, ioaddr + 0x4);
170
+		OUTB(0xa0, ioaddr + 0x8);
171
+		printf
172
+		    ("Software Data Protection for Bios ROM at %04x has been enabled\n",
173
+		     ioaddr);
174
+	} else if (strcmp(argv[2], "unprotect") == 0) {
175
+		OUTL(0x5555, ioaddr + 0x4);
176
+		OUTB(0xaa, ioaddr + 0x8);
177
+		OUTL(0x2aaa, ioaddr + 0x4);
178
+		OUTB(0x55, ioaddr + 0x8);
179
+		OUTL(0x5555, ioaddr + 0x4);
180
+		OUTB(0x80, ioaddr + 0x8);
181
+		OUTL(0x5555, ioaddr + 0x4);
182
+		OUTB(0xaa, ioaddr + 0x8);
183
+		OUTL(0x2aaa, ioaddr + 0x4);
184
+		OUTB(0x55, ioaddr + 0x8);
185
+		OUTL(0x5555, ioaddr + 0x4);
186
+		OUTB(0x20, ioaddr + 0x8);
187
+		printf
188
+		    ("Software Data Protection for Bios ROM at %04x has been disabled\n",
189
+		     ioaddr);
190
+	} else if (strcmp(argv[2], "id") == 0) {
191
+		OUTL(0x5555, ioaddr + 0x4);
192
+		OUTB(0xaa, ioaddr + 0x8);
193
+		OUTL(0x2aaa, ioaddr + 0x4);
194
+		OUTB(0x55, ioaddr + 0x8);
195
+		OUTL(0x5555, ioaddr + 0x4);
196
+		OUTB(0x90, ioaddr + 0x8);
197
+		/* 10ms delay needed */
198
+		printf("Manufacturer ID - ");
199
+		/* manuf. id */
200
+		OUTL(0x0000, ioaddr + 0x4);
201
+		printf("%02x\n", inb(ioaddr + 0x8));
202
+		/* device id */
203
+		OUTL(0x0001, ioaddr + 0x4);
204
+		printf("Device ID - %02x\n", inb(ioaddr + 0x8));
205
+		/* undo the funky chicken */
206
+		OUTL(0x5555, ioaddr + 0x4);
207
+		OUTB(0xaa, ioaddr + 0x8);
208
+		OUTL(0x2aaa, ioaddr + 0x4);
209
+		OUTB(0x55, ioaddr + 0x8);
210
+		OUTL(0x5555, ioaddr + 0x4);
211
+		OUTB(0xf0, ioaddr + 0x8);
212
+	} else if(strcmp(argv[2], "bootrom") == 0) {
213
+		printf("bootrom fix\n");
214
+		write_eeprom(ioaddr, 6, 19, 0x160);
215
+	} else if (strcmp(argv[2], "read") == 0) {
216
+		for (i = 0; i < 65536; i++) {
217
+			OUTL(i, ioaddr + 0x4);
218
+			b = inb(ioaddr + 0x8);
219
+			write(1, &b, 1);
220
+		}
221
+	} else if (strcmp(argv[2], "prog") == 0) {
222
+		/* program the rom in 128 bute chunks */
223
+		for (i = 0, n = 0; i < 65536; i += n) {
224
+			n = read(0, buf, 128);
225
+			if (n == 0)
226
+				break;
227
+			if (n < 0) {
228
+				perror("File Error");
229
+				exit(-3);
230
+			}
231
+			/* disable SDP temporarily for programming a sector */
232
+			OUTL(0x5555, ioaddr + 0x4);
233
+			OUTB(0xaa, ioaddr + 0x8);
234
+			OUTL(0x2aaa, ioaddr + 0x4);
235
+			OUTB(0x55, ioaddr + 0x8);
236
+			OUTL(0x5555, ioaddr + 0x4);
237
+			OUTB(0xa0, ioaddr + 0x8);
238
+			for (j = 0; j < n; j++) {
239
+				OUTL(i + j, ioaddr + 0x4);
240
+				OUTB(buf[j], ioaddr + 0x8);
241
+			}
242
+			/* wait for the programming of this sector to coomplete */
243
+			while (inb(ioaddr + 0x8) != buf[j - 1]);
244
+		}
155 245
 	}
156
-	/* wait for the programming of this sector to coomplete */
157
-	while (inb(ioaddr+0x8) != buf[j-1])
158
-	  ;
159
-      }
160
-    }
161
-
162
-    /* Set the register window to 3 for the 3c905b */
163
-    OUTW(0x803, ioaddr+0xe);
164
-    /* restore the receiver status */
165
-    OUTL(recvrstat, ioaddr);
166
-    return 0;
246
+
247
+	/* Set the register window to 3 for the 3c905b */
248
+	OUTW(0x803, ioaddr + 0xe);
249
+	/* restore the receiver status */
250
+	OUTL(recvrstat, ioaddr);
251
+	return 0;
167 252
 }
168 253
 
169
-#endif /* __i386__ */
254
+#endif				/* __i386__ */

+ 215
- 59
contrib/3c90xutil/cromutil.c View File

@@ -1,101 +1,257 @@
1
-/* 
2
- * 3c905cutil.c - perform various control ops on the 3C905C bios rom
3
- *             which we assume to be an AT49BV512
1
+/*
2
+ * JLdL 21Jun04.
3
+ *
4
+ * cromutil.c
5
+ *
6
+ * Perform various control operations on the flash EEPROM of
7
+ * _ the 3COM models 3C905C or 3C905CX network cards, in order
8
+ * _ to write a boot program such as Etherboot into it.
9
+ *
10
+ * This program is meant for the Linux operating system only,
11
+ * _ and only for the i386 architecture.
12
+ *
13
+ * The flash EEPROM usually used in these cards is the AT49BV512
14
+ * _ chip, which has 512 Kbit (64 KByte). Another possible chip,
15
+ * _ which is equivalent to this one, is the SST39VF512.
16
+ *
17
+ * Added alternative read128 and prog128 commands for cards with
18
+ * _ the SST29EE020 fast page-write (super-)flash EEPROM, which
19
+ * _ has 2 Mbit (256 KByte), and which has to be programmed in
20
+ * _ a 128-byte page mode. NOTE: it seems that the card can
21
+ * _ address only the first half of the memory in this chip,
22
+ * _ so only 128 Kbytes are actually available for use.
23
+ *
24
+ * Added a few informative messages and a detailed help message.
4 25
  *
5 26
  */
6 27
 
7 28
 #ifndef __i386__
8
-#  error "This program can't compile or run on non-intel computers"
29
+#  error "This program can't compile or run on non-Intel computers"
9 30
 #else
10 31
 
11 32
 #include <stdio.h>
12 33
 #include <stdlib.h>
13 34
 #include <unistd.h>
14 35
 #include <sys/io.h>
36
+#include <string.h>
15 37
 
16 38
 int main(int argc, char **argv)
17 39
 {
18
-  unsigned int ioaddr, i, n;
40
+  /* Counters. */
41
+  unsigned int i, j, n;
42
+  /* For ROM chips larger than 64 KB, a long integer
43
+     _ is needed for the global byte counter. */
44
+  unsigned long k;
45
+  /* The I/O address of the card. */
46
+  unsigned int ioaddr;
47
+  /* Storage for a byte. */
19 48
   unsigned char b;
49
+  /* Storage for a page. */
50
+  unsigned char buf[128];
51
+
52
+  /* Initialize a few things to avoid compiler warnings. */
53
+  i=0; j=0; n=0; k=0;
20 54
 
21
-  setuid(0); /* if we're setuid, do it really */
55
+  /* Verify the command-line parameters; write
56
+     _ out an usage message if needed. */
22 57
   if (argc != 3) {
23
-    printf("Usage: romid ioaddr [erase|id|read >file|prog <file]\n");
58
+    /* Exactly 2 command line parameters are needed. */
59
+    printf("Usage: ./cromutil ioaddr command [(>|<) file]\n");
60
+    printf(" (try './cromutil 0x0000 help' for details)\n");
24 61
     exit(-1);
25 62
   }
63
+
64
+  /* Set the UID to root if possible. */
65
+  setuid(0);
66
+
67
+  /* Get port-access permissions for in{blw}/out{blw}. */
26 68
   if (iopl(3)) {
27 69
     perror("iopl()");
28 70
     exit(1);
29 71
   }
72
+
73
+  /* Pass the I/O address of the card to a variable. */
30 74
   sscanf(argv[1],"%x",&ioaddr);
31 75
 
32
-  /* Set the register window to 0 for the 3C905C */
76
+  /* Set the register window to 0. */
33 77
   outw(0x800, ioaddr+0xe);
34 78
 
35
-  if (strcmp(argv[2], "erase") == 0) {
36
-    /* do the funky chicken to erase the rom contents */
37
-    outl(0x5555, ioaddr+0x4);
38
-    outb(0xaa, ioaddr+0x8);
39
-    outl(0x2aaa, ioaddr+0x4);
40
-    outb(0x55, ioaddr+0x8);
41
-    outl(0x5555, ioaddr+0x4);
42
-    outb(0x80, ioaddr+0x8);
43
-    outl(0x5555, ioaddr+0x4);
44
-    outb(0xaa, ioaddr+0x8);
45
-    outl(0x2aaa, ioaddr+0x4);
46
-    outb(0x55, ioaddr+0x8);
47
-    outl(0x5555, ioaddr+0x4);
48
-    outb(0x10, ioaddr+0x8);
49
-    sleep (1);
50
-    printf("Bios ROM at %04x has been erased\n", ioaddr);
51
-  } else if (strcmp(argv[2], "id") == 0) {
52
-    outl(0x5555, ioaddr+0x4);
53
-    outb(0xaa, ioaddr+0x8);
54
-    outl(0x2aaa, ioaddr+0x4);
55
-    outb(0x55, ioaddr+0x8);
56
-    outl(0x5555, ioaddr+0x4);
57
-    outb(0x90, ioaddr+0x8);
58
-    /* 10ms delay needed */
59
-    printf("Manufacturer ID - ");
60
-    /* manuf. id */
79
+  /*
80
+   * Execute the requested command.
81
+   *
82
+   * "id": get and write out the ID numbers.
83
+   */
84
+  if (strcmp(argv[2], "id") == 0) {
85
+    /* Software ID entry command sequence. */
86
+    outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
87
+    outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
88
+    outl(0x5555, ioaddr+0x4); outb(0x90, ioaddr+0x8);
89
+    /* A 10 ms delay is needed. */
90
+    usleep(10000);
91
+    /* Get the manufacturer id. */
61 92
     outl(0x0000, ioaddr+0x4);
62
-    printf("%02x\n", inb(ioaddr+0x8));
63
-    /* device id */
93
+    printf("Manufacturer ID - %02x\n", inb(ioaddr+0x8));
94
+    /* Get the device id. */
64 95
     outl(0x0001, ioaddr+0x4);
65 96
     printf("Device ID - %02x\n", inb(ioaddr+0x8));
66
-    /* undo the funky chicken */
67
-    outl(0x5555, ioaddr+0x4);
68
-    outb(0xaa, ioaddr+0x8);
69
-    outl(0x2aaa, ioaddr+0x4);
70
-    outb(0x55, ioaddr+0x8);
71
-    outl(0x5555, ioaddr+0x4);
72
-    outb(0xf0, ioaddr+0x8);
73
-  } else if (strcmp(argv[2], "read") == 0) {
74
-    for (i = 0; i < 65536; i++) {
75
-      outl(i, ioaddr+0x4);
97
+    /* Software ID exit command sequence. */
98
+    outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
99
+    outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
100
+    outl(0x5555, ioaddr+0x4); outb(0xf0, ioaddr+0x8);
101
+  }
102
+  /*
103
+   * "read": read data from the 512 Kbit ROM.
104
+   */
105
+  else if (strcmp(argv[2], "read") == 0) {
106
+    /* Loop over the whole ROM. */
107
+    for (k = 0; k < 65536; k++) {
108
+      outl(k, ioaddr+0x4);
109
+      b = inb(ioaddr+0x8);
110
+      write(1, &b, 1);
111
+    }
112
+    /* Write out an informative message. */
113
+    perror("Read 65536 bytes from ROM");
114
+  }
115
+  /*
116
+   * "read128": this alternative is for the 2 Mbit ROM.
117
+   */
118
+  else if (strcmp(argv[2], "read128") == 0) {
119
+    /* Loop over the accessible part of the ROM. */
120
+    for (k = 0; k < 131072; k++) {
121
+      outl(k, ioaddr+0x4);
76 122
       b = inb(ioaddr+0x8);
77 123
       write(1, &b, 1);
78 124
     }
79
-  } else if (strcmp(argv[2], "prog") == 0) {
80
-    for (i = 0; i < 65536; i++) {
81
-      n = read(0, &b, 1);
125
+    /* Write out an informative message. */
126
+    perror("Read 131072 bytes from ROM");
127
+  }
128
+  /*
129
+   * "erase": erase the ROM contents.
130
+   */
131
+  else if (strcmp(argv[2], "erase") == 0) {
132
+    /* Software chip-erase command sequence. */
133
+    outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
134
+    outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
135
+    outl(0x5555, ioaddr+0x4); outb(0x80, ioaddr+0x8);
136
+    outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
137
+    outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
138
+    outl(0x5555, ioaddr+0x4); outb(0x10, ioaddr+0x8);
139
+    /* Wait a bit. */
140
+    sleep(1);
141
+    /* Write out an informative message. */
142
+    printf("Bios ROM at %04x has been erased: Success\n", ioaddr);
143
+  }
144
+  /*
145
+   * "prog": program the 512 Kbit ROM.
146
+   */
147
+  else if (strcmp(argv[2], "prog") == 0) {
148
+    /* Loop over the bytes in pages, to
149
+       _ allow for a progress report. */
150
+    for (j = 0; j < 512; j++) {
151
+      for (i = 0; i < 128; i++) {
152
+	/* If this program is to run on a diskless node,
153
+	   _ must read in the byte _before_ changing the
154
+	   _ mode of the chip, or NFS may block. */
155
+	n = read(0, &b, 1);
156
+	/* At EOF exit the inner loop. */
157
+	if (n == 0)
158
+	  break;
159
+	if (n < 0) {
160
+	  perror("Input File Error");
161
+	  exit(-3);
162
+	}
163
+	/* Disable SDP temporarily for programming a byte. */
164
+	outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
165
+	outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
166
+	outl(0x5555, ioaddr+0x4); outb(0xA0, ioaddr+0x8);
167
+	/* Calculate the address of the byte. */
168
+	k=i+128*j;
169
+	/* Program this byte. */
170
+	outl(k, ioaddr+0x4); outb(b, ioaddr+0x8);
171
+	/* Wait for the programming of this byte to complete. */
172
+	while (inb(ioaddr+0x8) != b)
173
+	  ;
174
+      }
175
+      /* At EOF exit the outer loop. */
176
+      if (n == 0)
177
+	break;
178
+      /* Write out a progress report. */
179
+      printf("."); fflush(NULL);
180
+    }
181
+    /* Write out an informative message. */
182
+    printf("\nWrote %ld bytes to ROM: Success\n", k);
183
+  }
184
+  /*
185
+   * "prog128": this alternative is for the 2 Mbit ROM.
186
+   */
187
+  else if (strcmp(argv[2], "prog128") == 0) {
188
+    /* Loop over the accessible pages; the card can
189
+       _ access only the first half of the chip. */
190
+    for (j = 0; j < 1024; j++) {
191
+      /* If this program is to run on a diskless node,
192
+	 _ must read in the page _before_ changing the
193
+	 _ mode of the chip, or NFS may block. */
194
+      n = read(0, buf, 128);
195
+      /* At EOF exit the loop. */
82 196
       if (n == 0)
83 197
 	break;
84 198
       if (n < 0) {
85
-	perror("File Error");
199
+	perror("Input File Error");
86 200
 	exit(-3);
87 201
       }
88
-      outl(0x5555, ioaddr+0x4);
89
-      outb(0xaa, ioaddr+0x8);
90
-      outl(0x2aaa, ioaddr+0x4);
91
-      outb(0x55, ioaddr+0x8);
92
-      outl(0x5555, ioaddr+0x4);
93
-      outb(0xA0, ioaddr+0x8);
94
-      outl(i, ioaddr+0x4);
95
-      outb(b, ioaddr+0x8);
96
-      while (inb(ioaddr+0x8) != b)
202
+      /* Disable SDP temporarily for programming a page. */
203
+      outl(0x5555, ioaddr+0x4); outb(0xaa, ioaddr+0x8);
204
+      outl(0x2aaa, ioaddr+0x4); outb(0x55, ioaddr+0x8);
205
+      outl(0x5555, ioaddr+0x4); outb(0xA0, ioaddr+0x8);
206
+      /* Loop over the bytes in a page. */
207
+      for (i = 0; i < n; i++) {
208
+	/* Calculate the address of the byte. */
209
+	k=i+128*j;
210
+	/* Program this byte. */
211
+	outl(k, ioaddr+0x4); outb(buf[i], ioaddr+0x8);
212
+      }
213
+      /* Wait for the programming of this page to complete. */
214
+      while (inb(ioaddr+0x8) != buf[i-1])
97 215
 	;
216
+      /* Write out a progress report. */
217
+      printf("."); fflush(NULL);
98 218
     }
219
+    /* Write out an informative message. */
220
+    printf("\nWrote %d pages to ROM: Success\n", j);
221
+  }
222
+  /*
223
+   * "help": write out a detailed help message.
224
+   */
225
+  else if (strcmp(argv[2], "help") == 0) {
226
+    printf("This utility can be used to write data, usually boot loaders\n");
227
+    printf("  such as Etherboot, to the flash EEPROM of the 3COM models\n");
228
+    printf("  3C905C and 3C905CX network cards. You use it like this:\n");
229
+    printf("        ./cromutil ioaddr command [(>|<) file]\n");
230
+    printf("Here ioaddr is the hexadecimal I/O address of the card, such\n");
231
+    printf("  as 0xA123, in some cases you need input/output redirection\n");
232
+    printf("  from/to a file, and the command can be one of these:\n");
233
+    printf("  id               get the ID numbers of the card;\n");
234
+    printf("  read > file      read the contents of the ROM into a file;\n");
235
+    printf("  read128 > file   read the contents of the ROM into a file;\n");
236
+    printf("  erase            erase the whole ROM to the 1 state;\n");
237
+    printf("  prog < file      write the contents of a file into the ROM;\n");
238
+    printf("  prog128 < file   write the contents of a file into the ROM.\n");
239
+    printf("You can get the I/O address of the card using the commands\n");
240
+    printf("  'lspci -v', 'cat /proc/pci', or 'dmesg | grep -i 3C905C'.\n");
241
+    printf("The read and prog commands are to be used if the card has a\n");
242
+    printf("  traditional 512 Kb (64 KB) flash EEPROM chip, such as:\n");
243
+    printf("  | AT49BV512 | SST39VF512 |\n");
244
+    printf("The read128 and prog128 versions are for cards with a 2 Mb\n");
245
+    printf("  (128 KB usable) page-write flash EEPROM chip, such as:\n");
246
+    printf("  | SST29EE020 |\n");
247
+  }
248
+  /*
249
+   * Write out the usage message if an unknown command is used.
250
+   */
251
+  else {
252
+    printf("Usage: ./cromutil ioaddr command [(>|<) file]\n");
253
+    printf("(try './cromutil 0x0000 help' for details)\n");
254
+    exit(-1);
99 255
   }
100 256
   return 0;
101 257
 }

+ 104
- 0
contrib/3c90xutil/ocromutil.c View File

@@ -0,0 +1,104 @@
1
+/*
2
+ * 3c905cutil.c - perform various control ops on the 3C905C bios rom
3
+ *             which we assume to be an AT49BV512
4
+ *
5
+ */
6
+
7
+#ifndef __i386__
8
+#  error "This program can't compile or run on non-intel computers"
9
+#else
10
+
11
+#include <stdio.h>
12
+#include <stdlib.h>
13
+#include <unistd.h>
14
+#include <sys/io.h>
15
+#include <string.h>
16
+
17
+int main(int argc, char **argv)
18
+{
19
+  unsigned int ioaddr, i, n;
20
+  unsigned char b;
21
+
22
+  setuid(0); /* if we're setuid, do it really */
23
+  if (argc != 3) {
24
+    printf("Usage: romid ioaddr [erase|id|read >file|prog <file]\n");
25
+    exit(-1);
26
+  }
27
+  if (iopl(3)) {
28
+    perror("iopl()");
29
+    exit(1);
30
+  }
31
+  sscanf(argv[1],"%x",&ioaddr);
32
+
33
+  /* Set the register window to 0 for the 3C905C */
34
+  outw(0x800, ioaddr+0xe);
35
+
36
+  if (strcmp(argv[2], "erase") == 0) {
37
+    /* do the funky chicken to erase the rom contents */
38
+    outl(0x5555, ioaddr+0x4);
39
+    outb(0xaa, ioaddr+0x8);
40
+    outl(0x2aaa, ioaddr+0x4);
41
+    outb(0x55, ioaddr+0x8);
42
+    outl(0x5555, ioaddr+0x4);
43
+    outb(0x80, ioaddr+0x8);
44
+    outl(0x5555, ioaddr+0x4);
45
+    outb(0xaa, ioaddr+0x8);
46
+    outl(0x2aaa, ioaddr+0x4);
47
+    outb(0x55, ioaddr+0x8);
48
+    outl(0x5555, ioaddr+0x4);
49
+    outb(0x10, ioaddr+0x8);
50
+    sleep (1);
51
+    printf("Bios ROM at %04x has been erased\n", ioaddr);
52
+  } else if (strcmp(argv[2], "id") == 0) {
53
+    outl(0x5555, ioaddr+0x4);
54
+    outb(0xaa, ioaddr+0x8);
55
+    outl(0x2aaa, ioaddr+0x4);
56
+    outb(0x55, ioaddr+0x8);
57
+    outl(0x5555, ioaddr+0x4);
58
+    outb(0x90, ioaddr+0x8);
59
+    /* 10ms delay needed */
60
+    printf("Manufacturer ID - ");
61
+    /* manuf. id */
62
+    outl(0x0000, ioaddr+0x4);
63
+    printf("%02x\n", inb(ioaddr+0x8));
64
+    /* device id */
65
+    outl(0x0001, ioaddr+0x4);
66
+    printf("Device ID - %02x\n", inb(ioaddr+0x8));
67
+    /* undo the funky chicken */
68
+    outl(0x5555, ioaddr+0x4);
69
+    outb(0xaa, ioaddr+0x8);
70
+    outl(0x2aaa, ioaddr+0x4);
71
+    outb(0x55, ioaddr+0x8);
72
+    outl(0x5555, ioaddr+0x4);
73
+    outb(0xf0, ioaddr+0x8);
74
+  } else if (strcmp(argv[2], "read") == 0) {
75
+    for (i = 0; i < 65536; i++) {
76
+      outl(i, ioaddr+0x4);
77
+      b = inb(ioaddr+0x8);
78
+      write(1, &b, 1);
79
+    }
80
+  } else if (strcmp(argv[2], "prog") == 0) {
81
+    for (i = 0; i < 65536; i++) {
82
+      n = read(0, &b, 1);
83
+      if (n == 0)
84
+	break;
85
+      if (n < 0) {
86
+	perror("File Error");
87
+	exit(-3);
88
+      }
89
+      outl(0x5555, ioaddr+0x4);
90
+      outb(0xaa, ioaddr+0x8);
91
+      outl(0x2aaa, ioaddr+0x4);
92
+      outb(0x55, ioaddr+0x8);
93
+      outl(0x5555, ioaddr+0x4);
94
+      outb(0xA0, ioaddr+0x8);
95
+      outl(i, ioaddr+0x4);
96
+      outb(b, ioaddr+0x8);
97
+      while (inb(ioaddr+0x8) != b)
98
+	;
99
+    }
100
+  }
101
+  return 0;
102
+}
103
+
104
+#endif /* __i386__ */

Loading…
Cancel
Save