[3c90xutil] Update bromutil.c and cromutil.c.
[people/pcmattman/gpxe.git] / contrib / 3c90xutil / bromutil.c
1 /* 
2  * readutil.c - perform various control ops on the 3c509b bios rom
3  *
4  */
5
6 #ifndef __i386__
7 #  error "This program can't compile or run on non-intel computers"
8 #else
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14
15 #ifdef __FreeBSD__
16
17 #include <fcntl.h>
18 #include <machine/cpufunc.h>
19
20 #define OUTB(data, port)        outb(port, data)
21 #define OUTW(data, port)        outw(port, data)
22 #define OUTL(data, port)        outl(port, data)
23
24 #else
25
26 #include <sys/io.h>
27
28 #define OUTB(data, port)        outb(data, port)
29 #define OUTW(data, port)        outw(data, port)
30 #define OUTL(data, port)        outl(data, port)
31
32 #endif
33
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  */
41
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 }
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         }
127 #ifdef __FreeBSD__
128         /* get permissions for in/out{blw} */
129         open("/dev/io", O_RDONLY, 0);
130 #else
131         setuid(0);              /* if we're setuid, do it really */
132         if (iopl(3)) {
133                 perror("iopl()");
134                 exit(1);
135         }
136 #endif
137
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                 }
245         }
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;
252 }
253
254 #endif                          /* __i386__ */