]>
Commit | Line | Data |
---|---|---|
67c4f48a WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Denis Peter, MPL AG Switzerland, [email protected] | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | * | |
23 | */ | |
24 | ||
25 | /* NOT Used yet... | |
26 | add following code to PIP405.c : | |
27 | int testdram (void) | |
28 | { | |
29 | unsigned char s[32]; | |
30 | int i; | |
31 | ||
32 | i = getenv_r ("testmem", s, 32); | |
33 | if (i != 0) { | |
34 | i = (int) simple_strtoul (s, NULL, 10); | |
35 | if ((i > 0) && (i < 0xf)) { | |
36 | printf ("testing "); | |
37 | i = mem_test (0, ramsize, i); | |
38 | if (i > 0) | |
39 | printf ("ERROR "); | |
40 | else | |
41 | printf ("Ok "); | |
42 | } | |
43 | } | |
44 | return (1); | |
45 | } | |
46 | */ | |
47 | ||
48 | ||
49 | #include <common.h> | |
50 | #include <asm/processor.h> | |
51 | #include <405gp_i2c.h> | |
52 | ||
53 | #define FALSE 0 | |
54 | #define TRUE 1 | |
55 | ||
56 | #define TEST_QUIET 8 | |
57 | #define TEST_SHOW_PROG 4 | |
58 | #define TEST_SHOW_ERR 2 | |
59 | #define TEST_SHOW_ALL 1 | |
60 | ||
61 | #define TESTPAT1 0xAA55AA55 | |
62 | #define TESTPAT2 0x55AA55AA | |
63 | #define TEST_PASSED 0 | |
64 | #define TEST_FAILED 1 | |
65 | #define MEGABYTE (1024*1024) | |
66 | ||
67 | ||
67c4f48a WD |
68 | typedef struct { |
69 | volatile unsigned long pat1; | |
70 | volatile unsigned long pat2; | |
71 | } RAM_MEMTEST_PATTERN2; | |
72 | ||
73 | typedef struct { | |
74 | volatile unsigned long addr; | |
75 | } RAM_MEMTEST_ADDRLINE; | |
76 | ||
77 | static __inline unsigned long Swap_32 (unsigned long val) | |
78 | { | |
79 | return (((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)); | |
80 | } | |
81 | ||
82 | void testm_puts (int quiet, char *buf) | |
83 | { | |
84 | if ((quiet & TEST_SHOW_ALL) == TEST_SHOW_ALL) | |
85 | puts (buf); | |
86 | } | |
87 | ||
88 | ||
89 | void Write_Error (int mode, unsigned long addr, unsigned long expected, | |
90 | unsigned long actual) | |
91 | { | |
92 | ||
93 | char dispbuf[64]; | |
94 | ||
95 | sprintf (dispbuf, "\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ", | |
96 | addr, expected, actual); | |
97 | testm_puts (((mode & TEST_SHOW_ERR) == | |
98 | TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode, dispbuf); | |
99 | } | |
100 | ||
101 | ||
102 | /* | |
103 | * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2 | |
104 | */ | |
105 | ||
106 | ||
107 | void RAM_MemTest_WritePattern2 (unsigned long startaddr, | |
108 | unsigned long size, unsigned long pat1, | |
109 | unsigned long pat2) | |
110 | { | |
111 | RAM_MEMTEST_PATTERN2 *p, *pe; | |
112 | ||
113 | p = (RAM_MEMTEST_PATTERN2 *) startaddr; | |
114 | pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size); | |
115 | ||
116 | while (p < pe) { | |
117 | p->pat1 = pat1; | |
118 | p->pat2 = pat2; | |
119 | p++; | |
120 | } /* endwhile */ | |
121 | } | |
122 | ||
123 | /* | |
124 | * checks the memblock of <size> bytes from <startaddr> with pat1 and pat2 | |
125 | * returns the address of the first error or NULL if all is well | |
126 | */ | |
127 | ||
128 | void *RAM_MemTest_CheckPattern2 (int mode, unsigned long startaddr, | |
129 | unsigned long size, unsigned long pat1, | |
130 | unsigned long pat2) | |
131 | { | |
132 | RAM_MEMTEST_PATTERN2 *p, *pe; | |
133 | unsigned long actual1, actual2; | |
134 | ||
135 | p = (RAM_MEMTEST_PATTERN2 *) startaddr; | |
136 | pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size); | |
137 | ||
138 | while (p < pe) { | |
139 | actual1 = p->pat1; | |
140 | actual2 = p->pat2; | |
141 | ||
142 | if (actual1 != pat1) { | |
143 | Write_Error (mode, (unsigned long) &(p->pat1), pat1, actual1); | |
144 | return ((void *) &(p->pat1)); | |
145 | } | |
146 | /* endif */ | |
147 | if (actual2 != pat2) { | |
148 | Write_Error (mode, (unsigned long) &(p->pat2), pat2, actual2); | |
149 | return ((void *) &(p->pat2)); | |
150 | } | |
151 | /* endif */ | |
152 | p++; | |
153 | } /* endwhile */ | |
154 | ||
155 | return (NULL); | |
156 | } | |
157 | ||
158 | /* | |
159 | * fills the memblock of <size> bytes from <startaddr> with the address | |
160 | */ | |
161 | ||
162 | void RAM_MemTest_WriteAddrLine (unsigned long startaddr, | |
163 | unsigned long size, int swapped) | |
164 | { | |
165 | RAM_MEMTEST_ADDRLINE *p, *pe; | |
166 | ||
167 | p = (RAM_MEMTEST_ADDRLINE *) startaddr; | |
168 | pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size); | |
169 | ||
170 | if (!swapped) { | |
171 | while (p < pe) { | |
172 | p->addr = (unsigned long) p; | |
173 | p++; | |
174 | } /* endwhile */ | |
175 | } else { | |
176 | while (p < pe) { | |
177 | p->addr = Swap_32 ((unsigned long) p); | |
178 | p++; | |
179 | } /* endwhile */ | |
180 | } /* endif */ | |
181 | } | |
182 | ||
183 | /* | |
184 | * checks the memblock of <size> bytes from <startaddr> | |
185 | * returns the address of the error or NULL if all is well | |
186 | */ | |
187 | ||
188 | void *RAM_MemTest_CheckAddrLine (int mode, unsigned long startaddr, | |
189 | unsigned long size, int swapped) | |
190 | { | |
191 | RAM_MEMTEST_ADDRLINE *p, *pe; | |
192 | unsigned long actual, expected; | |
193 | ||
194 | p = (RAM_MEMTEST_ADDRLINE *) startaddr; | |
195 | pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size); | |
196 | ||
197 | if (!swapped) { | |
198 | while (p < pe) { | |
199 | actual = p->addr; | |
200 | expected = (unsigned long) p; | |
201 | if (actual != expected) { | |
202 | Write_Error (mode, (unsigned long) &(p->addr), expected, | |
203 | actual); | |
204 | return ((void *) &(p->addr)); | |
205 | } /* endif */ | |
206 | p++; | |
207 | } /* endwhile */ | |
208 | } else { | |
209 | while (p < pe) { | |
210 | actual = p->addr; | |
211 | expected = Swap_32 ((unsigned long) p); | |
212 | if (actual != expected) { | |
213 | Write_Error (mode, (unsigned long) &(p->addr), expected, | |
214 | actual); | |
215 | return ((void *) &(p->addr)); | |
216 | } /* endif */ | |
217 | p++; | |
218 | } /* endwhile */ | |
219 | } /* endif */ | |
220 | ||
221 | return (NULL); | |
222 | } | |
223 | ||
224 | /* | |
225 | * checks the memblock of <size> bytes from <startaddr+size> | |
226 | * returns the address of the error or NULL if all is well | |
227 | */ | |
228 | ||
229 | void *RAM_MemTest_CheckAddrLineReverse (int mode, unsigned long startaddr, | |
230 | unsigned long size, int swapped) | |
231 | { | |
232 | RAM_MEMTEST_ADDRLINE *p, *pe; | |
233 | unsigned long actual, expected; | |
234 | ||
235 | p = (RAM_MEMTEST_ADDRLINE *) (startaddr + size - sizeof (p->addr)); | |
236 | pe = (RAM_MEMTEST_ADDRLINE *) startaddr; | |
237 | ||
238 | if (!swapped) { | |
239 | while (p > pe) { | |
240 | actual = p->addr; | |
241 | expected = (unsigned long) p; | |
242 | if (actual != expected) { | |
243 | Write_Error (mode, (unsigned long) &(p->addr), expected, | |
244 | actual); | |
245 | return ((void *) &(p->addr)); | |
246 | } /* endif */ | |
247 | p--; | |
248 | } /* endwhile */ | |
249 | } else { | |
250 | while (p > pe) { | |
251 | actual = p->addr; | |
252 | expected = Swap_32 ((unsigned long) p); | |
253 | if (actual != expected) { | |
254 | Write_Error (mode, (unsigned long) &(p->addr), expected, | |
255 | actual); | |
256 | return ((void *) &(p->addr)); | |
257 | } /* endif */ | |
258 | p--; | |
259 | } /* endwhile */ | |
260 | } /* endif */ | |
261 | ||
262 | return (NULL); | |
263 | } | |
264 | ||
265 | /* | |
266 | * fills the memblock of <size> bytes from <startaddr> with walking bit pattern | |
267 | */ | |
268 | ||
269 | void RAM_MemTest_WriteWalkBit (unsigned long startaddr, unsigned long size) | |
270 | { | |
271 | volatile unsigned long *p, *pe; | |
272 | unsigned long i; | |
273 | ||
274 | p = (unsigned long *) startaddr; | |
275 | pe = (unsigned long *) (startaddr + size); | |
276 | i = 0; | |
277 | ||
278 | while (p < pe) { | |
279 | *p = 1UL << i; | |
280 | i = (i + 1 + (((unsigned long) p) >> 7)) % 32; | |
281 | p++; | |
282 | } /* endwhile */ | |
283 | } | |
284 | ||
285 | /* | |
286 | * checks the memblock of <size> bytes from <startaddr> | |
287 | * returns the address of the error or NULL if all is well | |
288 | */ | |
289 | ||
290 | void *RAM_MemTest_CheckWalkBit (int mode, unsigned long startaddr, | |
291 | unsigned long size) | |
292 | { | |
293 | volatile unsigned long *p, *pe; | |
294 | unsigned long actual, expected; | |
295 | unsigned long i; | |
296 | ||
297 | p = (unsigned long *) startaddr; | |
298 | pe = (unsigned long *) (startaddr + size); | |
299 | i = 0; | |
300 | ||
301 | while (p < pe) { | |
302 | actual = *p; | |
303 | expected = (1UL << i); | |
304 | if (actual != expected) { | |
305 | Write_Error (mode, (unsigned long) p, expected, actual); | |
306 | return ((void *) p); | |
307 | } /* endif */ | |
308 | i = (i + 1 + (((unsigned long) p) >> 7)) % 32; | |
309 | p++; | |
310 | } /* endwhile */ | |
311 | ||
312 | return (NULL); | |
313 | } | |
314 | ||
315 | /* | |
316 | * fills the memblock of <size> bytes from <startaddr> with "random" pattern | |
317 | */ | |
318 | ||
319 | void RAM_MemTest_WriteRandomPattern (unsigned long startaddr, | |
320 | unsigned long size, | |
321 | unsigned long *pat) | |
322 | { | |
323 | unsigned long i, p; | |
324 | ||
325 | p = *pat; | |
326 | ||
327 | for (i = 0; i < (size / 4); i++) { | |
328 | *(unsigned long *) (startaddr + i * 4) = p; | |
329 | if ((p % 2) > 0) { | |
330 | p ^= i; | |
331 | p >>= 1; | |
332 | p |= 0x80000000; | |
333 | } else { | |
334 | p ^= ~i; | |
335 | p >>= 1; | |
336 | } /* endif */ | |
337 | } /* endfor */ | |
338 | *pat = p; | |
339 | } | |
340 | ||
341 | /* | |
342 | * checks the memblock of <size> bytes from <startaddr> | |
343 | * returns the address of the error or NULL if all is well | |
344 | */ | |
345 | ||
346 | void *RAM_MemTest_CheckRandomPattern (int mode, unsigned long startaddr, | |
347 | unsigned long size, | |
348 | unsigned long *pat) | |
349 | { | |
350 | void *perr = NULL; | |
351 | unsigned long i, p, p1; | |
352 | ||
353 | p = *pat; | |
354 | ||
355 | for (i = 0; i < (size / 4); i++) { | |
356 | p1 = *(unsigned long *) (startaddr + i * 4); | |
357 | if (p1 != p) { | |
358 | if (perr == NULL) { | |
359 | Write_Error (mode, startaddr + i * 4, p, p1); | |
360 | perr = (void *) (startaddr + i * 4); | |
361 | } /* endif */ | |
362 | } | |
363 | /* endif */ | |
364 | if ((p % 2) > 0) { | |
365 | p ^= i; | |
366 | p >>= 1; | |
367 | p |= 0x80000000; | |
368 | } else { | |
369 | p ^= ~i; | |
370 | p >>= 1; | |
371 | } /* endif */ | |
372 | } /* endfor */ | |
373 | ||
374 | *pat = p; | |
375 | return (perr); | |
376 | } | |
377 | ||
378 | ||
379 | void RAM_MemTest_WriteData1 (unsigned long startaddr, unsigned long size, | |
380 | unsigned long *pat) | |
381 | { | |
382 | RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT1, TESTPAT2); | |
383 | } | |
384 | ||
385 | void *RAM_MemTest_CheckData1 (int mode, unsigned long startaddr, | |
386 | unsigned long size, unsigned long *pat) | |
387 | { | |
388 | return (RAM_MemTest_CheckPattern2 | |
389 | (mode, startaddr, size, TESTPAT1, TESTPAT2)); | |
390 | } | |
391 | ||
392 | void RAM_MemTest_WriteData2 (unsigned long startaddr, unsigned long size, | |
393 | unsigned long *pat) | |
394 | { | |
395 | RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT2, TESTPAT1); | |
396 | } | |
397 | ||
398 | void *RAM_MemTest_CheckData2 (int mode, unsigned long startaddr, | |
399 | unsigned long size, unsigned long *pat) | |
400 | { | |
401 | return (RAM_MemTest_CheckPattern2 | |
402 | (mode, startaddr, size, TESTPAT2, TESTPAT1)); | |
403 | } | |
404 | ||
405 | void RAM_MemTest_WriteAddr1 (unsigned long startaddr, unsigned long size, | |
406 | unsigned long *pat) | |
407 | { | |
408 | RAM_MemTest_WriteAddrLine (startaddr, size, FALSE); | |
409 | } | |
410 | ||
411 | void *RAM_MemTest_Check1Addr1 (int mode, unsigned long startaddr, | |
412 | unsigned long size, unsigned long *pat) | |
413 | { | |
414 | return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, FALSE)); | |
415 | } | |
416 | ||
417 | void *RAM_MemTest_Check2Addr1 (int mode, unsigned long startaddr, | |
418 | unsigned long size, unsigned long *pat) | |
419 | { | |
420 | return (RAM_MemTest_CheckAddrLineReverse | |
421 | (mode, startaddr, size, FALSE)); | |
422 | } | |
423 | ||
424 | void RAM_MemTest_WriteAddr2 (unsigned long startaddr, unsigned long size, | |
425 | unsigned long *pat) | |
426 | { | |
427 | RAM_MemTest_WriteAddrLine (startaddr, size, TRUE); | |
428 | } | |
429 | ||
430 | void *RAM_MemTest_Check1Addr2 (int mode, unsigned long startaddr, | |
431 | unsigned long size, unsigned long *pat) | |
432 | { | |
433 | return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, TRUE)); | |
434 | } | |
435 | ||
436 | void *RAM_MemTest_Check2Addr2 (int mode, unsigned long startaddr, | |
437 | unsigned long size, unsigned long *pat) | |
438 | { | |
439 | return (RAM_MemTest_CheckAddrLineReverse | |
440 | (mode, startaddr, size, TRUE)); | |
441 | } | |
442 | ||
443 | ||
67c4f48a WD |
444 | typedef struct { |
445 | void (*test_write) (unsigned long startaddr, unsigned long size, | |
446 | unsigned long *pat); | |
447 | char *test_write_desc; | |
448 | void *(*test_check1) (int mode, unsigned long startaddr, | |
449 | unsigned long size, unsigned long *pat); | |
450 | void *(*test_check2) (int mode, unsigned long startaddr, | |
451 | unsigned long size, unsigned long *pat); | |
452 | } RAM_MEMTEST_FUNC; | |
453 | ||
454 | ||
455 | #define TEST_STAGES 5 | |
33149b88 | 456 | static RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = { |
67c4f48a WD |
457 | {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1, |
458 | NULL}, | |
459 | {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2, | |
460 | NULL}, | |
461 | {RAM_MemTest_WriteAddr1, "address line test...\n", | |
462 | RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1}, | |
463 | {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n", | |
464 | RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2}, | |
465 | {RAM_MemTest_WriteRandomPattern, "random data test...\n", | |
466 | RAM_MemTest_CheckRandomPattern, NULL} | |
467 | }; | |
468 | ||
33149b88 WD |
469 | void mem_test_reloc(void) |
470 | { | |
471 | DECLARE_GLOBAL_DATA_PTR; | |
472 | unsigned long addr; | |
473 | int i; | |
474 | for (i=0; i< TEST_STAGES; i++) { | |
475 | addr = (ulong) (test_stage[i].test_write) + gd->reloc_off; | |
476 | test_stage[i].test_write= | |
477 | (void (*) (unsigned long startaddr, unsigned long size, | |
478 | unsigned long *pat))addr; | |
479 | addr = (ulong) (test_stage[i].test_write_desc) + gd->reloc_off; | |
480 | test_stage[i].test_write_desc=(char *)addr; | |
481 | if(test_stage[i].test_check1) { | |
482 | addr = (ulong) (test_stage[i].test_check1) + gd->reloc_off; | |
483 | test_stage[i].test_check1= | |
484 | (void *(*) (int mode, unsigned long startaddr, | |
485 | unsigned long size, unsigned long *pat))addr; | |
486 | } | |
487 | if(test_stage[i].test_check2) { | |
488 | addr = (ulong) (test_stage[i].test_check2) + gd->reloc_off; | |
489 | test_stage[i].test_check2= | |
490 | (void *(*) (int mode, unsigned long startaddr, | |
491 | unsigned long size, unsigned long *pat))addr; | |
492 | } | |
493 | } | |
494 | } | |
67c4f48a WD |
495 | |
496 | ||
27b207fd | 497 | int mem_test (unsigned long start, unsigned long ramsize, int quiet) |
67c4f48a WD |
498 | { |
499 | unsigned long errors, stage; | |
500 | unsigned long startaddr, size, i; | |
501 | const unsigned long blocksize = 0x80000; /* check in 512KB blocks */ | |
502 | unsigned long *perr; | |
503 | unsigned long rdatapat; | |
504 | char dispbuf[80]; | |
505 | int status = TEST_PASSED; | |
506 | int prog = 0; | |
507 | ||
508 | errors = 0; | |
509 | startaddr = start; | |
510 | size = ramsize; | |
511 | if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) { | |
512 | prog++; | |
513 | printf ("."); | |
514 | } | |
515 | sprintf (dispbuf, "\nMemory Test: addr = 0x%lx size = 0x%lx\n", | |
516 | startaddr, size); | |
517 | testm_puts (quiet, dispbuf); | |
518 | for (stage = 0; stage < TEST_STAGES; stage++) { | |
519 | sprintf (dispbuf, test_stage[stage].test_write_desc); | |
520 | testm_puts (quiet, dispbuf); | |
521 | /* fill SDRAM */ | |
522 | rdatapat = 0x12345678; | |
523 | sprintf (dispbuf, "writing block: "); | |
524 | testm_puts (quiet, dispbuf); | |
525 | for (i = 0; i < size; i += blocksize) { | |
526 | sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize); | |
527 | testm_puts (quiet, dispbuf); | |
528 | test_stage[stage].test_write (startaddr + i, blocksize, | |
529 | &rdatapat); | |
530 | } /* endfor */ | |
531 | sprintf (dispbuf, "\n"); | |
532 | testm_puts (quiet, dispbuf); | |
533 | if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) { | |
534 | prog++; | |
535 | printf ("."); | |
536 | } | |
537 | /* check SDRAM */ | |
538 | rdatapat = 0x12345678; | |
539 | sprintf (dispbuf, "checking block: "); | |
540 | testm_puts (quiet, dispbuf); | |
541 | for (i = 0; i < size; i += blocksize) { | |
542 | sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize); | |
543 | testm_puts (quiet, dispbuf); | |
544 | if ((perr = | |
545 | test_stage[stage].test_check1 (quiet, startaddr + i, | |
546 | blocksize, | |
547 | &rdatapat)) != NULL) { | |
548 | status = TEST_FAILED; | |
549 | } /* endif */ | |
550 | } /* endfor */ | |
551 | sprintf (dispbuf, "\n"); | |
552 | testm_puts (quiet, dispbuf); | |
553 | if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) { | |
554 | prog++; | |
555 | printf ("."); | |
556 | } | |
557 | if (test_stage[stage].test_check2 != NULL) { | |
558 | /* check2 SDRAM */ | |
559 | sprintf (dispbuf, "2nd checking block: "); | |
560 | rdatapat = 0x12345678; | |
561 | testm_puts (quiet, dispbuf); | |
562 | for (i = 0; i < size; i += blocksize) { | |
563 | sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize); | |
564 | testm_puts (quiet, dispbuf); | |
565 | if ((perr = | |
566 | test_stage[stage].test_check2 (quiet, startaddr + i, | |
567 | blocksize, | |
568 | &rdatapat)) != NULL) { | |
569 | status = TEST_FAILED; | |
570 | } /* endif */ | |
571 | } /* endfor */ | |
572 | sprintf (dispbuf, "\n"); | |
573 | testm_puts (quiet, dispbuf); | |
574 | if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) { | |
575 | prog++; | |
576 | printf ("."); | |
577 | } | |
578 | } | |
579 | ||
580 | } /* next stage */ | |
581 | if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) { | |
582 | while (prog-- > 0) | |
583 | printf ("\b \b"); | |
584 | } | |
585 | ||
586 | if (status == TEST_FAILED) | |
587 | errors++; | |
588 | ||
589 | return (errors); | |
590 | } |