]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/etin/debris/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / etin / debris / flash.c
1 /*
2  * board/eva/flash.c
3  *
4  * (C) Copyright 2002
5  * Sangmoon Kim, Etin Systems, dogoil@etinsys.com.
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27 #include <asm/processor.h>
28 #include <asm/pci_io.h>
29 #include <mpc824x.h>
30
31 int (*do_flash_erase)(flash_info_t*, uint32_t, uint32_t);
32 int (*write_dword)(flash_info_t*, ulong, uint64_t);
33
34 typedef uint64_t cfi_word;
35
36 #define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr))
37
38 #define cfi_write(flash, val, addr) \
39         move64((cfi_word*)&val, \
40                         (cfi_word*)(flash->start[0] + addr))
41
42 #define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x)))
43
44 static void write32(unsigned long addr, uint32_t value)
45 {
46         *(volatile uint32_t*)(addr) = value;
47         asm volatile("sync");
48 }
49
50 static uint32_t read32(unsigned long addr)
51 {
52         uint32_t value;
53         value = *(volatile uint32_t*)addr;
54         asm volatile("sync");
55         return value;
56 }
57
58 static cfi_word cfi_cmd(flash_info_t *flash, uint8_t cmd, uint32_t addr)
59 {
60         uint32_t base = flash->start[0];
61         uint32_t val=(cmd << 16) | cmd;
62         addr <<= 3;
63         write32(base + addr, val);
64         return addr;
65 }
66
67 static uint16_t cfi_read_query(flash_info_t *flash, uint32_t addr)
68 {
69         uint32_t base = flash->start[0];
70         addr <<= 3;
71         return (uint16_t)read32(base + addr);
72 }
73
74 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
75
76 static void move64(uint64_t *src, uint64_t *dest)
77 {
78         asm volatile("lfd  0, 0(3)\n\t" /* fpr0   =  *scr       */
79          "stfd 0, 0(4)"         /* *dest  =  fpr0       */
80          : : : "fr0" );         /* Clobbers fr0         */
81         return;
82 }
83
84 static int cfi_write_dword(flash_info_t *flash, ulong dest, cfi_word data)
85 {
86         unsigned long start;
87         cfi_word status = 0;
88
89         status = cfi_read(flash, dest);
90         data &= status;
91
92         cfi_cmd(flash, 0x40, 0);
93         cfi_write(flash, data, dest);
94
95         udelay(10);
96         start = get_timer (0);
97         for(;;) {
98                 status = cfi_read(flash, dest);
99                 status &= CMD(0x80);
100                 if(status == CMD(0x80))
101                         break;
102                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
103                         cfi_cmd(flash, 0xff, 0);
104                         return 1;
105                 }
106                 udelay(1);
107         }
108         cfi_cmd(flash, 0xff, 0);
109
110         return 0;
111 }
112
113 static int jedec_write_dword (flash_info_t *flash, ulong dest, cfi_word data)
114 {
115         ulong start;
116         cfi_word status = 0;
117
118         status = cfi_read(flash, dest);
119         if(status != CMD(0xffff)) return 2;
120
121         cfi_cmd(flash, 0xaa, 0x555);
122         cfi_cmd(flash, 0x55, 0x2aa);
123         cfi_cmd(flash, 0xa0, 0x555);
124
125         cfi_write(flash, data, dest);
126
127         udelay(10);
128         start = get_timer (0);
129         status = ~data;
130         while(status != data) {
131                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
132                         return 1;
133                 status = cfi_read(flash, dest);
134                 udelay(1);
135         }
136         return 0;
137 }
138
139 static __inline__ unsigned long get_msr(void)
140 {
141         unsigned long msr;
142         __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
143         return msr;
144 }
145
146 static __inline__ void set_msr(unsigned long msr)
147 {
148         __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
149 }
150
151 int write_buff (flash_info_t *flash, uchar *src, ulong addr, ulong cnt)
152 {
153         ulong wp;
154         int i, s, l, rc;
155         cfi_word data;
156         uint8_t *t = (uint8_t*)&data;
157         unsigned long base = flash->start[0];
158         uint32_t msr;
159
160         if (flash->flash_id == FLASH_UNKNOWN)
161                 return 4;
162
163         if (cnt == 0)
164                 return 0;
165
166         addr -= base;
167
168         msr = get_msr();
169         set_msr(msr|MSR_FP);
170
171         wp = (addr & ~7);   /* get lower word aligned address */
172
173         if((addr-wp) != 0) {
174                 data = cfi_read(flash, wp);
175                 s = addr & 7;
176                 l = ( cnt < (8-s) ) ? cnt : (8-s);
177                 for(i = 0; i < l; i++)
178                         t[s+i] = *src++;
179                 if ((rc = write_dword(flash, wp, data)) != 0)
180                         goto DONE;
181                 wp += 8;
182                 cnt -= l;
183         }
184
185         while (cnt >= 8) {
186                 for (i = 0; i < 8; i++)
187                         t[i] = *src++;
188                 if ((rc = write_dword(flash, wp, data)) != 0)
189                         goto DONE;
190                 wp  += 8;
191                 cnt -= 8;
192         }
193
194         if (cnt == 0) {
195                 rc = 0;
196                 goto DONE;
197         }
198
199         data = cfi_read(flash, wp);
200         for(i = 0; i < cnt; i++)
201                 t[i] = *src++;
202         rc = write_dword(flash, wp, data);
203 DONE:
204         set_msr(msr);
205         return rc;
206 }
207
208 static int cfi_erase_oneblock(flash_info_t *flash, uint32_t sect)
209 {
210         int sa;
211         int flag;
212         ulong start, last, now;
213         cfi_word status;
214
215         flag = disable_interrupts();
216
217         sa = (flash->start[sect] - flash->start[0]);
218         write32(flash->start[sect], 0x00200020);
219         write32(flash->start[sect], 0x00d000d0);
220
221         if (flag)
222                 enable_interrupts();
223
224         udelay(1000);
225         start = get_timer (0);
226         last  = start;
227
228         for (;;) {
229                 status = cfi_read(flash, sa);
230                 status &= CMD(0x80);
231                 if (status == CMD(0x80))
232                         break;
233                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
234                         cfi_cmd(flash, 0xff, 0);
235                         printf ("Timeout\n");
236                         return ERR_TIMOUT;
237                 }
238
239                 if ((now - last) > 1000) {
240                         serial_putc ('.');
241                         last = now;
242                 }
243                 udelay(10);
244         }
245         cfi_cmd(flash, 0xff, 0);
246         return ERR_OK;
247 }
248
249 static int cfi_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
250 {
251         int sect;
252         int rc = ERR_OK;
253
254         for (sect = s_first; sect <= s_last; sect++) {
255                 if (flash->protect[sect] == 0) {
256                         rc = cfi_erase_oneblock(flash, sect);
257                         if (rc != ERR_OK) break;
258                 }
259         }
260         printf (" done\n");
261         return rc;
262 }
263
264 static int jedec_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
265 {
266         int sect;
267         cfi_word status;
268         int sa = -1;
269         int flag;
270         ulong start, last, now;
271
272         flag = disable_interrupts();
273
274         cfi_cmd(flash, 0xaa, 0x555);
275         cfi_cmd(flash, 0x55, 0x2aa);
276         cfi_cmd(flash, 0x80, 0x555);
277         cfi_cmd(flash, 0xaa, 0x555);
278         cfi_cmd(flash, 0x55, 0x2aa);
279         for ( sect = s_first; sect <= s_last; sect++) {
280                 if (flash->protect[sect] == 0) {
281                         sa = flash->start[sect] - flash->start[0];
282                         write32(flash->start[sect], 0x00300030);
283                 }
284         }
285         if (flag)
286                 enable_interrupts();
287
288         if (sa < 0)
289                 goto DONE;
290
291         udelay (1000);
292         start = get_timer (0);
293         last  = start;
294         for(;;) {
295                 status = cfi_read(flash, sa);
296                 if (status == CMD(0xffff))
297                         break;
298
299                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
300                         printf ("Timeout\n");
301                         return ERR_TIMOUT;
302                 }
303
304                 if ((now - last) > 1000) {
305                         serial_putc ('.');
306                         last = now;
307                 }
308                 udelay(10);
309         }
310 DONE:
311         cfi_cmd(flash, 0xf0, 0);
312
313         printf (" done\n");
314
315         return ERR_OK;
316 }
317
318 int flash_erase (flash_info_t *flash, int s_first, int s_last)
319 {
320         int sect;
321         int prot;
322
323         if ((s_first < 0) || (s_first > s_last)) {
324                 if (flash->flash_id == FLASH_UNKNOWN)
325                         printf ("- missing\n");
326                 else
327                         printf ("- no sectors to erase\n");
328                 return ERR_NOT_ERASED;
329         }
330         if (flash->flash_id == FLASH_UNKNOWN) {
331                 printf ("Can't erase unknown flash type - aborted\n");
332                 return ERR_NOT_ERASED;
333         }
334
335         prot = 0;
336         for (sect = s_first; sect <= s_last; sect++)
337                 if (flash->protect[sect]) prot++;
338
339         if (prot)
340                 printf ("- Warning: %d protected sectors will not be erased!\n",
341                                                                 prot);
342         else
343                 printf ("\n");
344
345         return do_flash_erase(flash, s_first, s_last);
346 }
347
348 struct jedec_flash_info {
349         const uint16_t mfr_id;
350         const uint16_t dev_id;
351         const char *name;
352         const int DevSize;
353         const int InterfaceDesc;
354         const int NumEraseRegions;
355         const ulong regions[4];
356 };
357
358 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
359
360 #define SIZE_1MiB 20
361 #define SIZE_2MiB 21
362 #define SIZE_4MiB 22
363
364 static const struct jedec_flash_info jedec_table[] = {
365         {
366                 mfr_id: (uint16_t)AMD_MANUFACT,
367                 dev_id: (uint16_t)AMD_ID_LV800T,
368                 name: "AMD AM29LV800T",
369                 DevSize: SIZE_1MiB,
370                 NumEraseRegions: 4,
371                 regions: {ERASEINFO(0x10000,15),
372                           ERASEINFO(0x08000,1),
373                           ERASEINFO(0x02000,2),
374                           ERASEINFO(0x04000,1)
375                 }
376         }, {
377                 mfr_id: (uint16_t)AMD_MANUFACT,
378                 dev_id: (uint16_t)AMD_ID_LV800B,
379                 name: "AMD AM29LV800B",
380                 DevSize: SIZE_1MiB,
381                 NumEraseRegions: 4,
382                 regions: {ERASEINFO(0x10000,15),
383                           ERASEINFO(0x08000,1),
384                           ERASEINFO(0x02000,2),
385                           ERASEINFO(0x04000,1)
386                 }
387         }, {
388                 mfr_id: (uint16_t)AMD_MANUFACT,
389                 dev_id: (uint16_t)AMD_ID_LV160T,
390                 name: "AMD AM29LV160T",
391                 DevSize: SIZE_2MiB,
392                 NumEraseRegions: 4,
393                 regions: {ERASEINFO(0x10000,31),
394                           ERASEINFO(0x08000,1),
395                           ERASEINFO(0x02000,2),
396                           ERASEINFO(0x04000,1)
397                 }
398         }, {
399                 mfr_id: (uint16_t)AMD_MANUFACT,
400                 dev_id: (uint16_t)AMD_ID_LV160B,
401                 name: "AMD AM29LV160B",
402                 DevSize: SIZE_2MiB,
403                 NumEraseRegions: 4,
404                 regions: {ERASEINFO(0x04000,1),
405                           ERASEINFO(0x02000,2),
406                           ERASEINFO(0x08000,1),
407                           ERASEINFO(0x10000,31)
408                 }
409         }, {
410                 mfr_id: (uint16_t)AMD_MANUFACT,
411                 dev_id: (uint16_t)AMD_ID_LV320T,
412                 name: "AMD AM29LV320T",
413                 DevSize: SIZE_4MiB,
414                 NumEraseRegions: 2,
415                 regions: {ERASEINFO(0x10000,63),
416                           ERASEINFO(0x02000,8)
417                 }
418
419         }, {
420                 mfr_id: (uint16_t)AMD_MANUFACT,
421                 dev_id: (uint16_t)AMD_ID_LV320B,
422                 name: "AMD AM29LV320B",
423                 DevSize: SIZE_4MiB,
424                 NumEraseRegions: 2,
425                 regions: {ERASEINFO(0x02000,8),
426                           ERASEINFO(0x10000,63)
427                 }
428         }
429 };
430
431 static ulong cfi_init(uint32_t base,  flash_info_t *flash)
432 {
433         int sector;
434         int block;
435         int block_count;
436         int offset = 0;
437         int reverse = 0;
438         int primary;
439         int mfr_id;
440         int dev_id;
441
442         flash->start[0] = base;
443         cfi_cmd(flash, 0xF0, 0);
444         cfi_cmd(flash, 0x98, 0);
445         if ( !( cfi_read_query(flash, 0x10) == 'Q' &&
446                 cfi_read_query(flash, 0x11) == 'R' &&
447                 cfi_read_query(flash, 0x12) == 'Y' )) {
448                 cfi_cmd(flash, 0xff, 0);
449                 return 0;
450         }
451
452         flash->size = 1 << cfi_read_query(flash, 0x27);
453         flash->size *= 4;
454         block_count = cfi_read_query(flash, 0x2c);
455         primary = cfi_read_query(flash, 0x15);
456         if ( cfi_read_query(flash, primary + 4) == 0x30)
457                 reverse = (cfi_read_query(flash, 0x1) & 0x01);
458         else
459                 reverse = (cfi_read_query(flash, primary+15) == 3);
460
461         flash->sector_count = 0;
462
463         for ( block = reverse ? block_count - 1 : 0;
464                       reverse ? block >= 0      : block < block_count;
465                       reverse ? block--         : block ++) {
466                 int sector_size =
467                         (cfi_read_query(flash, 0x2d + block*4+2) |
468                         (cfi_read_query(flash, 0x2d + block*4+3) << 8)) << 8;
469                 int sector_count =
470                         (cfi_read_query(flash, 0x2d + block*4+0) |
471                         (cfi_read_query(flash, 0x2d + block*4+1) << 8)) + 1;
472                 for(sector = 0; sector < sector_count; sector++) {
473                         flash->start[flash->sector_count++] = base + offset;
474                         offset += sector_size * 4;
475                 }
476         }
477         mfr_id = cfi_read_query(flash, 0x00);
478         dev_id = cfi_read_query(flash, 0x01);
479
480         cfi_cmd(flash, 0xff, 0);
481
482         flash->flash_id = (mfr_id << 16) | dev_id;
483
484         for (sector = 0; sector < flash->sector_count; sector++) {
485                 write32(flash->start[sector], 0x00600060);
486                 write32(flash->start[sector], 0x00d000d0);
487         }
488         cfi_cmd(flash, 0xff, 0);
489
490         for (sector = 0; sector < flash->sector_count; sector++)
491                 flash->protect[sector] = 0;
492
493         do_flash_erase = cfi_erase;
494         write_dword = cfi_write_dword;
495
496         return flash->size;
497 }
498
499 static ulong jedec_init(unsigned long base, flash_info_t *flash)
500 {
501         int i;
502         int block, block_count;
503         int sector, offset;
504         int mfr_id, dev_id;
505         flash->start[0] = base;
506         cfi_cmd(flash, 0xF0, 0x000);
507         cfi_cmd(flash, 0xAA, 0x555);
508         cfi_cmd(flash, 0x55, 0x2AA);
509         cfi_cmd(flash, 0x90, 0x555);
510         mfr_id = cfi_read_query(flash, 0x000);
511         dev_id = cfi_read_query(flash, 0x0001);
512         cfi_cmd(flash, 0xf0, 0x000);
513
514         for(i=0; i<sizeof(jedec_table)/sizeof(struct jedec_flash_info); i++) {
515                 if((jedec_table[i].mfr_id == mfr_id) &&
516                         (jedec_table[i].dev_id == dev_id)) {
517
518                         flash->flash_id = (mfr_id << 16) | dev_id;
519                         flash->size = 1 << jedec_table[0].DevSize;
520                         flash->size *= 4;
521                         block_count = jedec_table[i].NumEraseRegions;
522                         offset = 0;
523                         flash->sector_count = 0;
524                         for (block = 0; block < block_count; block++) {
525                                 int sector_size = jedec_table[i].regions[block];
526                                 int sector_count = (sector_size & 0xff) + 1;
527                                 sector_size >>= 8;
528                                 for (sector=0; sector<sector_count; sector++) {
529                                         flash->start[flash->sector_count++] =
530                                                 base + offset;
531                                         offset += sector_size * 4;
532                                 }
533                         }
534                         break;
535                 }
536         }
537
538         for (sector = 0; sector < flash->sector_count; sector++)
539                 flash->protect[sector] = 0;
540
541         do_flash_erase = jedec_erase;
542         write_dword = jedec_write_dword;
543
544         return flash->size;
545 }
546
547 inline void mtibat1u(unsigned int x)
548 {
549         __asm__ __volatile__ ("mtspr   530, %0" :: "r" (x));
550 }
551
552 inline void mtibat1l(unsigned int x)
553 {
554         __asm__ __volatile__ ("mtspr   531, %0" :: "r" (x));
555 }
556
557 inline void mtdbat1u(unsigned int x)
558 {
559         __asm__ __volatile__ ("mtspr   538, %0" :: "r" (x));
560 }
561
562 inline void mtdbat1l(unsigned int x)
563 {
564         __asm__ __volatile__ ("mtspr   539, %0" :: "r" (x));
565 }
566
567 unsigned long flash_init (void)
568 {
569         unsigned long size = 0;
570         int i;
571         unsigned int msr;
572
573         /* BAT1 */
574         CONFIG_WRITE_WORD(ERCR3, 0x0C00000C);
575         CONFIG_WRITE_WORD(ERCR4, 0x0800000C);
576         msr = get_msr();
577         set_msr(msr & ~(MSR_IR | MSR_DR));
578         mtibat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
579         mtibat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
580         mtdbat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
581         mtdbat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
582         set_msr(msr);
583
584         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
585                 flash_info[i].flash_id = FLASH_UNKNOWN;
586         size = cfi_init(FLASH_BASE0_PRELIM, &flash_info[0]);
587         if (!size)
588                 size = jedec_init(FLASH_BASE0_PRELIM, &flash_info[0]);
589
590         if (flash_info[0].flash_id == FLASH_UNKNOWN)
591                 printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
592                         size, size<<20);
593
594         return size;
595 }
596
597 void flash_print_info  (flash_info_t *flash)
598 {
599         int i;
600         int k;
601         int size;
602         int erased;
603         volatile unsigned long *p;
604
605         if (flash->flash_id == FLASH_UNKNOWN) {
606                 printf ("missing or unknown FLASH type\n");
607                 flash_init();
608         }
609
610         if (flash->flash_id == FLASH_UNKNOWN) {
611                 printf ("missing or unknown FLASH type\n");
612                 return;
613         }
614
615         switch (((flash->flash_id) >> 16) & 0xff) {
616         case 0x01:
617                 printf ("AMD ");
618                 break;
619         case 0x04:
620                 printf("FUJITSU ");
621                 break;
622         case 0x20:
623                 printf("STM ");
624                 break;
625         case 0xBF:
626                 printf("SST ");
627                 break;
628         case 0x89:
629         case 0xB0:
630                 printf("INTEL ");
631                 break;
632         default:
633                 printf ("Unknown Vendor ");
634                 break;
635         }
636
637         switch ((flash->flash_id) & 0xffff) {
638         case (uint16_t)AMD_ID_LV800T:
639                 printf ("AM29LV800T\n");
640                 break;
641         case (uint16_t)AMD_ID_LV800B:
642                 printf ("AM29LV800B\n");
643                 break;
644         case (uint16_t)AMD_ID_LV160T:
645                 printf ("AM29LV160T\n");
646                 break;
647         case (uint16_t)AMD_ID_LV160B:
648                 printf ("AM29LV160B\n");
649                 break;
650         case (uint16_t)AMD_ID_LV320T:
651                 printf ("AM29LV320T\n");
652                 break;
653         case (uint16_t)AMD_ID_LV320B:
654                 printf ("AM29LV320B\n");
655                 break;
656         case (uint16_t)INTEL_ID_28F800C3T:
657                 printf ("28F800C3T\n");
658                 break;
659         case (uint16_t)INTEL_ID_28F800C3B:
660                 printf ("28F800C3B\n");
661                 break;
662         case (uint16_t)INTEL_ID_28F160C3T:
663                 printf ("28F160C3T\n");
664                 break;
665         case (uint16_t)INTEL_ID_28F160C3B:
666                 printf ("28F160C3B\n");
667                 break;
668         case (uint16_t)INTEL_ID_28F320C3T:
669                 printf ("28F320C3T\n");
670                 break;
671         case (uint16_t)INTEL_ID_28F320C3B:
672                 printf ("28F320C3B\n");
673                 break;
674         case (uint16_t)INTEL_ID_28F640C3T:
675                 printf ("28F640C3T\n");
676                 break;
677         case (uint16_t)INTEL_ID_28F640C3B:
678                 printf ("28F640C3B\n");
679                 break;
680         default:
681                 printf ("Unknown Chip Type\n");
682                 break;
683         }
684
685         if (flash->size >= (1 << 20)) {
686                 printf ("  Size: %ld MB in %d Sectors\n",
687                                 flash->size >> 20, flash->sector_count);
688         } else {
689                 printf ("  Size: %ld kB in %d Sectors\n",
690                                 flash->size >> 10, flash->sector_count);
691         }
692
693         printf ("  Sector Start Addresses:");
694         for (i = 0; i < flash->sector_count; ++i) {
695                 /* Check if whole sector is erased*/
696                 if (i != (flash->sector_count-1))
697                         size = flash->start[i+1] - flash->start[i];
698                 else
699                         size = flash->start[0] + flash->size - flash->start[i];
700
701                 erased = 1;
702                 p = (volatile unsigned long *)flash->start[i];
703                 size = size >> 2;        /* divide by 4 for longword access */
704                 for (k=0; k<size; k++) {
705                         if (*p++ != 0xffffffff) {
706                                 erased = 0;
707                                 break;
708                         }
709                 }
710
711                 if ((i % 5) == 0)
712                         printf ("\n   ");
713
714                 printf (" %08lX%s%s",
715                         flash->start[i],
716                         erased ? " E" : "  ",
717                         flash->protect[i] ? "RO " : "   ");
718         }
719         printf ("\n");
720 }