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
-FILES = cromutil bromutil
1
+FILES = cromutil ocromutil bromutil
2
 
2
 
3
 INCLUDEDIR = /usr/include
3
 INCLUDEDIR = /usr/include
4
 CFLAGS = -O2 -fomit-frame-pointer -Wall -I$(INCLUDEDIR)
4
 CFLAGS = -O2 -fomit-frame-pointer -Wall -I$(INCLUDEDIR)

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

8
 differentiate the versions.  cromutil is for 3C905C and bromutil is
8
 differentiate the versions.  cromutil is for 3C905C and bromutil is
9
 for 3C905B.
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
 Be careful. You can easily erase your Flash memory using these
60
 Be careful. You can easily erase your Flash memory using these
12
 utilities.  Make *sure* to back them up first using the "read"
61
 utilities.  Make *sure* to back them up first using the "read"
13
 command. You must "erase" before using "prog" to program the chip with
62
 command. You must "erase" before using "prog" to program the chip with

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

10
 #include <stdio.h>
10
 #include <stdio.h>
11
 #include <stdlib.h>
11
 #include <stdlib.h>
12
 #include <unistd.h>
12
 #include <unistd.h>
13
+#include <string.h>
13
 
14
 
14
 #ifdef __FreeBSD__
15
 #ifdef __FreeBSD__
15
 
16
 
30
 
31
 
31
 #endif
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
 #ifdef __FreeBSD__
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
 #else
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
 #endif
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
-/* 
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
 #ifndef __i386__
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
 #else
30
 #else
10
 
31
 
11
 #include <stdio.h>
32
 #include <stdio.h>
12
 #include <stdlib.h>
33
 #include <stdlib.h>
13
 #include <unistd.h>
34
 #include <unistd.h>
14
 #include <sys/io.h>
35
 #include <sys/io.h>
36
+#include <string.h>
15
 
37
 
16
 int main(int argc, char **argv)
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
   unsigned char b;
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
   if (argc != 3) {
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
     exit(-1);
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
   if (iopl(3)) {
68
   if (iopl(3)) {
27
     perror("iopl()");
69
     perror("iopl()");
28
     exit(1);
70
     exit(1);
29
   }
71
   }
72
+
73
+  /* Pass the I/O address of the card to a variable. */
30
   sscanf(argv[1],"%x",&ioaddr);
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
   outw(0x800, ioaddr+0xe);
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
     outl(0x0000, ioaddr+0x4);
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
     outl(0x0001, ioaddr+0x4);
95
     outl(0x0001, ioaddr+0x4);
65
     printf("Device ID - %02x\n", inb(ioaddr+0x8));
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
       b = inb(ioaddr+0x8);
122
       b = inb(ioaddr+0x8);
77
       write(1, &b, 1);
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
       if (n == 0)
196
       if (n == 0)
83
 	break;
197
 	break;
84
       if (n < 0) {
198
       if (n < 0) {
85
-	perror("File Error");
199
+	perror("Input File Error");
86
 	exit(-3);
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
   return 0;
256
   return 0;
101
 }
257
 }

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

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