Line data Source code
1 : // This file (mcs.cc) was created by Ron Rechenmacher <ron@fnal.gov> on
2 : // May 19, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3 : // or COPYING file. If you do not have such a file, one can be obtained by
4 : // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5 : // $RCSfile: .emacs.gnu,v $
6 : const char *rev = "$Revision: 1.23 $$Date: 2012/01/23 15:32:40 $";
7 :
8 : #include <getopt.h> // getopt_long
9 : #include <libgen.h> // basename
10 : #include <stdio.h> // printf
11 : #include <stdlib.h> // setenv
12 :
13 : #include "trace.h" // TRACE
14 :
15 : #include "pcidevl_ioctl.h"
16 :
17 : #define USAGE \
18 : "\
19 : usage: %s [opts] <mcs_file>\n\
20 : -e just erase (then exit)\n\
21 : --swap-data swap the data\n\
22 : ", \
23 : basename(argv[0])
24 :
25 : int g_fd;
26 :
27 : // 32bit byte and half word swap
28 0 : inline uint32_t swab32(uint32_t a)
29 : {
30 0 : return ((0xFF000000 & a) >> 24) | ((0x00FF0000 & a) >> 8) | ((0x0000FF00 & a) << 8) | ((0x000000FF & a) << 24);
31 : } // swab32
32 :
33 0 : int set_prom_program_data_reg32(uint32_t data)
34 : {
35 : ioc_ioop ioop;
36 0 : ioop.offset = 0x9400;
37 0 : ioop.ops_mask = ioop_write;
38 0 : ioop.write_val = data;
39 0 : TRACE(5, "set_prom_program_status_reg32 0x%08x ==>", ioop.write_val);
40 0 : int sts = ioctl(g_fd, IOC_IOOP, &ioop);
41 0 : return sts;
42 : }
43 :
44 0 : int get_prom_program_status_reg32(uint32_t *val)
45 : {
46 : ioc_ioop ioop;
47 0 : ioop.offset = 0x9404;
48 0 : ioop.ops_mask = ioop_read;
49 0 : int sts = ioctl(g_fd, IOC_IOOP, &ioop);
50 0 : *val = ioop.read_val;
51 0 : TRACE(5, "get_prom_program_status_reg32 val=0x%08x", ioop.read_val);
52 0 : return sts;
53 : }
54 :
55 0 : int main(int argc, char *argv[])
56 : {
57 0 : int opt_v = 0;
58 0 : int opt_just_erase = 0;
59 0 : int opt_data_swap = 0;
60 : extern int optind; /* for getopt */
61 : char devfile[13]; /* /dev/pcidevX */
62 :
63 : while (1)
64 : {
65 0 : int opt, option_index = 0;
66 : static struct option long_options[] = {
67 : /* name, has_arg, int* flag, val_for_flag */
68 : {"swap-data", 0, 0, 1},
69 : {0, 0, 0, 0},
70 : };
71 0 : opt = getopt_long(argc, argv, "?hVve", long_options, &option_index);
72 0 : if (opt == -1) break;
73 0 : switch (opt)
74 : {
75 0 : case '?':
76 : case 'h':
77 0 : printf(USAGE);
78 0 : exit(0);
79 : break;
80 0 : case 'V':
81 0 : printf("%s\n", rev);
82 0 : return (0);
83 : break;
84 0 : case 'v':
85 0 : opt_v++;
86 0 : break;
87 0 : case 'e':
88 0 : opt_just_erase = 1;
89 0 : break;
90 0 : case 1:
91 0 : opt_data_swap = 1;
92 0 : break;
93 0 : default:
94 0 : printf("?? getopt returned character code 0%o ??\n", opt);
95 : }
96 0 : }
97 0 : if (argc - optind < 2)
98 : {
99 0 : printf("Need mcs_file and device number\n");
100 0 : printf(USAGE);
101 0 : return (-1);
102 : }
103 :
104 0 : setenv("TRACE_LVLS", "0xf", 0); // setenv( "TRACE_NAME", "mcs", 0 );
105 0 : TRACE_CNTL("lvlset", 0xffffffffULL, strtoull(getenv("TRACE_LVLS"), NULL, 0), 0ULL);
106 0 : TRACE_CNTL("mode", 3ULL);
107 0 : TRACE(1, "hello");
108 :
109 0 : snprintf(devfile, 13, "/dev/" PCIDEVL_DEV_FILE, atoi(argv[optind++]));
110 :
111 0 : int fd = open(devfile, O_RDONLY);
112 0 : if (fd == -1)
113 : {
114 0 : perror("open"); /*return (1);*/
115 : }
116 0 : g_fd = fd;
117 :
118 0 : FILE *stream = fopen(argv[optind], "r");
119 :
120 0 : int lines = 0, data_bytes = 0;
121 0 : unsigned StartBlockSet = 0, StartBlock, EndBlock, LastAddr = 0;
122 : int bytecount;
123 : unsigned address, RecType, data, checksum;
124 : int sts;
125 0 : while ((sts = fscanf(stream, ":%2x%4x%2x", (unsigned *)&bytecount, &address, &RecType)) == 3)
126 : {
127 0 : if (RecType == 4)
128 : {
129 0 : if (StartBlockSet != 1)
130 : {
131 0 : StartBlockSet = 1;
132 0 : sts = fscanf(stream, "%4x", &StartBlock);
133 0 : if (sts != 1)
134 : {
135 0 : TRACE(0, "Error getting StartBlock");
136 0 : return -1;
137 : }
138 : }
139 : else
140 : {
141 0 : if (fscanf(stream, "%4x", &EndBlock) != 1)
142 : {
143 0 : TRACE(0, "Error getting EndBlock");
144 0 : return -1;
145 : }
146 : }
147 0 : bytecount -= 2;
148 : }
149 0 : else if (RecType == 0)
150 : {
151 0 : LastAddr = address;
152 : }
153 0 : while (bytecount--)
154 : {
155 0 : sts = fscanf(stream, "%2x", &data);
156 0 : if (sts != 1)
157 : {
158 0 : printf("did not get data\n");
159 0 : return -1;
160 : }
161 : }
162 0 : sts = fscanf(stream, "%2x\n", &checksum);
163 0 : lines++;
164 : }
165 0 : int FileSize = (((EndBlock << 16) | LastAddr) / 2) - ((StartBlock << 16) / 2); // file size in bytes
166 0 : TRACE(1, "got %d lines. StartBlock=0x%x EndBlock=0x%x LastAddr=0x%x FileSize=%d", lines, StartBlock, EndBlock,
167 : LastAddr, FileSize);
168 :
169 : // rewind
170 0 : fseek(stream, 0, SEEK_SET);
171 0 : lines = 0;
172 :
173 0 : uint32_t ReadMask = 0x1;
174 : uint32_t ReadData;
175 0 : sts = get_prom_program_status_reg32(&ReadData);
176 0 : if (sts) TRACE(0, "unexpected status");
177 0 : if ((ReadData & ReadMask) != ReadMask)
178 : {
179 0 : TRACE(0, "not ready");
180 0 : return -1;
181 : }
182 :
183 : // unlock all blocks
184 0 : uint32_t StartBlock_w = StartBlock / 2; // bytes to "words" (1 word == 2 bytes)
185 :
186 0 : sts = set_prom_program_data_reg32(0x53410000 | (StartBlock_w << 8));
187 0 : if (sts) TRACE(0, "unexpected status");
188 0 : sts = set_prom_program_data_reg32(0x45000000 | (((EndBlock << 16) | LastAddr) / 2));
189 0 : if (sts) TRACE(0, "unexpected status");
190 0 : sts = set_prom_program_data_reg32(0x556e6c6b);
191 0 : if (sts) TRACE(0, "unexpected status");
192 :
193 0 : ReadData = 0;
194 0 : uint32_t checks = 0;
195 0 : while ((ReadData & ReadMask) != ReadMask)
196 : {
197 0 : sts = get_prom_program_status_reg32(&ReadData);
198 0 : if (sts) TRACE(0, "unexpected status");
199 0 : checks++;
200 : }
201 0 : TRACE(1, "after unlock, checks=%u ReadData=0x%x", checks, ReadData);
202 :
203 : // Erase blocks
204 0 : sts = set_prom_program_data_reg32(0x45726173);
205 0 : if (sts) TRACE(0, "unexpected status");
206 0 : ReadData = checks = 0;
207 0 : while ((ReadData & ReadMask) != ReadMask)
208 : {
209 0 : sts = get_prom_program_status_reg32(&ReadData);
210 0 : if (sts) TRACE(0, "unexpected status");
211 0 : checks++;
212 : }
213 0 : TRACE(1, "after Erase, checks=%u ReadData=0x%x", checks, ReadData);
214 :
215 0 : if (opt_just_erase) return (0);
216 :
217 : // Program
218 0 : sts = set_prom_program_data_reg32(0x50726f67);
219 0 : if (sts) TRACE(0, "unexpected status");
220 :
221 0 : ReadMask = 0xff0000;
222 :
223 0 : while ((sts = fscanf(stream, ":%2x%4x%2x", (unsigned *)&bytecount, &address, &RecType)) == 3)
224 : {
225 0 : switch (RecType)
226 : {
227 0 : case 0:
228 0 : TRACE(4, "Data Record - bytecount=0x%02x, address0x%04x", bytecount, address);
229 0 : ReadData = checks = 0;
230 0 : if ((data_bytes % 64) == 0)
231 0 : while ((ReadData & ReadMask) != 0x800000)
232 : {
233 0 : sts = get_prom_program_status_reg32(&ReadData);
234 0 : if (sts) TRACE(0, "unexpected status");
235 0 : if ((ReadData & ReadMask) == 0x900000)
236 : {
237 0 : TRACE(0, "program error ReadData=0x%x checks=%u data_bytes=%d", ReadData, checks, data_bytes);
238 0 : return -1;
239 : }
240 0 : checks++;
241 0 : if (checks == 10000000)
242 : {
243 0 : TRACE(0, "program timeout ReadData=0x%x", ReadData);
244 0 : return -1;
245 : }
246 : }
247 0 : TRACE(1, "before set_prom_program_data_reg32, checks=%u data_bytes=%d", checks, data_bytes);
248 0 : while (bytecount > 0)
249 : {
250 0 : sts = fscanf(stream, "%8x", &data);
251 0 : if (sts != 1)
252 : {
253 0 : printf("did not get data\n");
254 0 : return -1;
255 : }
256 :
257 0 : if (opt_data_swap)
258 0 : sts = set_prom_program_data_reg32(swab32(data));
259 : else
260 0 : sts = set_prom_program_data_reg32(data);
261 0 : if (sts) TRACE(0, "unexpected status");
262 0 : bytecount -= 4;
263 0 : data_bytes += 4;
264 : }
265 0 : sts = fscanf(stream, "%2x\n", &checksum);
266 0 : if (sts != 1)
267 : {
268 0 : printf("did not get checksum\n");
269 0 : return -1;
270 : }
271 0 : break;
272 0 : case 1:
273 0 : TRACE(3, "End of File - bytecount=0x%02x, address0x%04x", bytecount, address);
274 0 : while (bytecount--)
275 : {
276 0 : sts = fscanf(stream, "%2x", &data);
277 0 : if (sts != 1)
278 : {
279 0 : printf("did not get data\n");
280 0 : return -1;
281 : }
282 : }
283 0 : sts = fscanf(stream, "%2x\n", &checksum);
284 0 : if (sts != 1)
285 : {
286 0 : printf("did not get checksum\n");
287 0 : return -1;
288 : }
289 0 : break;
290 0 : case 4:
291 0 : TRACE(3, "Extended Linear Address - bytecount=0x%02x, address0x%04x", bytecount, address);
292 0 : while (bytecount--)
293 : {
294 0 : sts = fscanf(stream, "%2x", &data);
295 0 : if (sts != 1)
296 : {
297 0 : printf("did not get data\n");
298 0 : return -1;
299 : }
300 : }
301 0 : sts = fscanf(stream, "%2x\n", &checksum);
302 0 : if (sts != 1)
303 : {
304 0 : printf("did not get checksum\n");
305 0 : return -1;
306 : }
307 0 : break;
308 0 : default:
309 0 : TRACE(1, "Programming - ignoring record type %d\n", RecType);
310 0 : while (bytecount--)
311 : {
312 0 : sts = fscanf(stream, "%2x", &data);
313 0 : if (sts != 1)
314 : {
315 0 : printf("did not get data\n");
316 0 : return -1;
317 : }
318 : }
319 0 : sts = fscanf(stream, "%2x\n", &checksum);
320 0 : if (sts != 1)
321 : {
322 0 : printf("did not get checksum\n");
323 0 : return -1;
324 : }
325 : }
326 0 : lines++;
327 : }
328 0 : TRACE(1, "got %d lines, %d data_bytes", lines, data_bytes);
329 :
330 0 : return (0);
331 : } // main
|