]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/h8300/generic/libs/boot/boot_fn.c
Added meaningful error message
[sysless.git] / arch / h8300 / generic / libs / boot / boot_fn.c
1 #include <types.h>
2 #include <cpu_def.h>
3 #include <system_def.h>
4 //#include <h8s2633h.h>
5 #include <mcu_regs.h>
6 #include "boot_fn.h"
7
8 #undef WITH_EXTERNAL_FLASH
9
10 #if 1
11  #define DEB_WR_HEX(...)
12 #else
13  #define DEB_WR_HEX(_hex,_digs) deb_wr_hex(_hex,_digs);
14  void deb_wr_hex(long hex, short digs);
15 #endif
16
17 #if 1
18   #define DEB_BLOG_INIT
19   #define DEB_BLOG(...)
20 #else
21   #define DEB_BLOG_INIT  do{ *(long*)0x280000=0x280000+4; } while(0)
22   #define DEB_BLOG(_val) do{ *((*(long**)0x280000)++)=_val; } while(0)
23 #endif
24
25 #ifdef WITH_EXTERNAL_FLASH
26   #define EXTERNAL_FLASH_START 0x40000
27   #define EXTERNAL_FLASH_END (0x40000+0xfffff)
28   int ExtFlProgRow(__u8 *addr, __u8 *data);
29   int ExtFlErase(__u8 *addr);
30 #endif /*WITH_EXTERNAL_FLASH*/
31
32
33 /* Enable watchdog with selected system clock prescaller */
34 /* 2, 64, 128, 512, 2048, 8192, 32768, 131072 */
35 void wdg_enable(int psel)
36 {
37   /* Enable power-on  reset of WDT owerflow */
38   *WDT_WRSTCSRw=(0x5a00 | 1*WRSTCSR_RSTEm | 0*WRSTCSR_RSTSm);
39   /* Select watchdog function and input clocks  */
40   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm |(psel & WTCSR0_CKSxm));
41   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm | 1*WTCSR0_TMEm | (psel & WTCSR0_CKSxm));
42 }
43
44 /* Disable watchdog */
45 void wdg_disable()
46 {
47   *WDT_WTCSR0w=(0xa500);
48 }
49
50 /* Clear watchdog */
51 void wdg_clear()
52 {
53   *WDT_WTCNT0w=(0x5a00);
54 }
55
56 #define TO_TEXT __attribute__ ((section (".text")))
57
58 #define PIC_ADR(_ptr,_var) \
59         { \
60           __asm__ ( \
61             "bsr 1f\n" \
62             "1:\tmov.l @sp+,%0\n" \
63             "\tadd.l %1-1b,%0\n" \
64             : "=r" (_ptr) : "i" (&(_var)) : "cc" \
65           ); \
66         }
67
68 static const unsigned long
69   flash_blocks[] TO_TEXT =
70         {0x00000,0x01000,0x02000,0x03000,0x04000,0x05000,0x06000,0x07000,
71          0x08000,0x10000,0x20000,0x30000,0x40000,0};
72
73 static const int
74   flash_block_count TO_TEXT =
75         sizeof(flash_blocks)/sizeof(unsigned long)-2;
76
77 #if 0
78 volatile void FlWait(long n)
79 {
80   long i=0;
81   volatile long x;
82   while (i<n*6){
83     i++;
84     x+=i;
85   }     
86 }
87 #else
88 volatile void FlWait(long n);
89
90 __asm__ (
91 ".global _FlWait\n"
92 "_FlWait:\n"
93 #if (CPU_SYS_HZ>16000000)
94 "       shll.l  er0"
95 #endif
96 "       mov.w   #1,r1\n"
97 "       bra     2f:8\n"
98 "1:     dec.w   #1,r1\n"
99 "       bne     1b:8\n"
100 "       nop\n"
101 "       mov.w   #2,r1\n"
102 "2:     dec.l   #1,er0\n"
103 "       bne     1b:8\n"
104 "       rts\n"
105 );
106
107 #endif
108
109 int FlAdr2Blk(unsigned long adr)
110 {
111   int bl=0;
112   unsigned long *blocks;
113   PIC_ADR(blocks,flash_blocks[0]);
114
115   if(adr<blocks[0]) return -1;
116   while(blocks[bl+1]){
117     if(adr<blocks[bl+1]) return bl;
118     bl++;
119   }
120   return -1;
121 }
122
123 /* Check if block number is blank */
124 int FlTest(int bl)
125 {
126   __u16 *p, *pe;
127   unsigned long *blocks;
128   PIC_ADR(blocks,flash_blocks[0]);
129   
130   if(bl>=flash_block_count) return -2;
131   if(bl<0) return -2;
132
133   /* No software control over Flash/External select */
134   /* *BCRL=(*BCRL & (EAE ^ 0x0ff)); */
135
136   p=(__u16*)blocks[bl];
137   pe=(__u16*)blocks[bl+1];
138   while(p<pe){
139     *p=0xffff;
140     FlWait(2);
141     if (*p!=0xffff) return -1;
142     p++;
143   }
144   return 0;
145 }
146
147 /* Erase block number */
148 int FlErase(int bl)
149 {
150   int n=100; /*N*/
151   if(bl>=flash_block_count) return -4;
152   if(bl<0) return -5;
153
154   if(FlTest(bl)==0) return 0;
155
156   if((*FLM_FLMCR1 & FLMCR1_FWEm)==0) return -1;
157
158   *FLM_FLMCR1=FLMCR1_SWE1m;
159   FlWait(1);            /*x*/
160   if(bl<8){
161     *FLM_EBR1=(1 << bl);
162     *FLM_EBR2=0;
163   }else{
164     *FLM_EBR1=0;
165     *FLM_EBR2=(1 << (bl-8));
166   }
167   while(n>0){
168     n--;
169     if(*FLM_FLMCR2 & FLMCR2_FLERm) goto fls_error;
170     wdg_enable(4+1);
171     *FLM_FLMCR1|=FLMCR1_ESU1m;
172     FlWait(100);                /*y*/
173     *FLM_FLMCR1|=FLMCR1_E1m;
174     FlWait(5000);               /*z=max10000*/
175     *FLM_FLMCR1&=~FLMCR1_E1m;
176     FlWait(10);                 /*alpha*/
177     *FLM_FLMCR2&=~FLMCR1_ESU1m;
178     FlWait(10);                 /*betha*/
179     wdg_disable();
180     if(*FLM_FLMCR2 & FLMCR2_FLERm) goto fls_error;
181     *FLM_FLMCR1|=FLMCR1_EV1m;
182     FlWait(6);                  /*gamma*/
183     if(FlTest(bl)==0){
184       *FLM_FLMCR1&=FLMCR1_SWE1m; /*clear EV1*/
185       FlWait(4);                /*ny*/
186       *FLM_FLMCR1=0;
187       return 0;
188     }
189     *FLM_FLMCR1&=FLMCR1_SWE1m; /*clear EV1*/
190     FlWait(4);                  /*ny*/
191   }
192   *FLM_FLMCR1=0;
193   FlWait(100);                  /*x1*/
194   return -2;
195   
196  fls_error:
197   *FLM_FLMCR1=0;
198   return -3;
199 }
200
201 void FlProgPulse(int time_zx)
202 {
203   wdg_enable(3+1);
204   *FLM_FLMCR1|=FLMCR1_PSU1m;
205   FlWait(50);                   /*y*/
206   *FLM_FLMCR1|=FLMCR1_P1m;
207   FlWait(time_zx);              /*z0,z1 or z2*/
208   *FLM_FLMCR1&=~FLMCR1_P1m;
209   FlWait(5);                    /*alpha*/
210   *FLM_FLMCR1&=FLMCR1_SWE1m; /*clear PSU1*/
211   FlWait(5);                    /*betha*/
212   wdg_disable();
213 }
214
215 /* Program data to address */
216 int FlProgRow(__u8 *adr, __u8 *data)
217 {
218   __u8 prog_data[FLASH_ROW];
219   int i;
220   int m;
221   int n;
222   __u8 *x;
223   __u8 c,d;
224   if((unsigned long)adr & (FLASH_ROW-1)) return -6;
225   if((*FLM_FLMCR1 & FLMCR1_FWEm)==0 ) return -5;
226  #ifdef WITH_EXTERNAL_FLASH
227   if(((__u32)adr>=EXTERNAL_FLASH_START)&&
228      ((__u32)adr<=EXTERNAL_FLASH_END)){
229     return ExtFlProgRow(adr,data);
230   }
231  #endif /*WITH_EXTERNAL_FLASH*/
232
233   x=adr;
234   for(i=FLASH_ROW;i--;x++){
235     if(*x!=0xff) return -4;
236   }
237   x=data;
238   for(i=0;i<FLASH_ROW;i++,x++) prog_data[i]=*x;
239
240   *FLM_FLMCR1=FLMCR1_SWE1m;
241   FlWait(1);                    /*x0*/
242
243   n=0;
244   while(n<100){                 /*N1+N2<1000*/
245     n++;
246     m=0;
247     i=0;
248     x=adr;
249     for(i=0;i<FLASH_ROW;i++,x++) *x=prog_data[i];
250     
251     FlProgPulse(n>6?150:25);    /*z0<30 or z2<200 if n>N1*/
252
253     *FLM_FLMCR1|=FLMCR1_PV1m;
254     FlWait(4);                  /*gamma*/
255     i=0;
256     x=adr;
257     for(i=0;i<FLASH_ROW;i+=2,x+=2){
258       *(__u16*)x=0xffff;
259       FlWait(2);                /*epsilon*/
260       *(__u16*)(prog_data+i)=*(__u16*)x;
261     } 
262     *FLM_FLMCR1&=FLMCR1_SWE1m; /*clear PV1*/
263     FlWait(2);                  /*ny*/
264     if(n<=6){                   /*N1*/
265       x=adr;
266       for(i=0;i<FLASH_ROW;i++,x++){
267         c=prog_data[i]; 
268         d=data[i];
269         if((~c&d)&0xff) goto fls_error;
270         if(c!=d) {
271           m=1;
272           /* DEB_BLOG(0xEE000000+(long)x); */
273           /* DEB_BLOG(0xEF000000+(__u16)(c<<8)+(__u8)d); */
274         }
275         *x=d|c;
276         prog_data[i]=d|~c;
277       }
278       
279       FlProgPulse(7);           /*z1<10*/
280       
281     }else{
282       for(i=0;i<FLASH_ROW;i++){
283         c=prog_data[i]; 
284         d=data[i];
285         if(c!=d) m=1;
286         if((~c&d)&0xff) goto fls_error;
287         prog_data[i]=d|~c;
288       }
289     }
290     if(m==0){
291       *FLM_FLMCR1=0;
292       FlWait(100);              /*x1*/
293       DEB_BLOG(0xED000000+n);
294       return 0;
295     }
296   }
297   *FLM_FLMCR1=0;
298   FlWait(100);                  /*x1*/
299   return -1;
300
301  fls_error:
302   *FLM_FLMCR1=0;
303   return -3;
304 }
305
306 int FlPrepBlk(unsigned long badr, unsigned long len)
307 {
308   int bl, blend, res;
309   bl=FlAdr2Blk(badr);
310   blend=FlAdr2Blk(badr+len-1);
311   if((bl<0)||(blend<0)) return -EBOOT_BLOCKADDR;
312   for(;bl<=blend;bl++){
313     if(FlTest(bl)){
314       res=FlErase(bl);
315       if(res<0) return res;
316     }
317   }
318   return 0;
319 }
320
321
322 #if 0
323 #define RS232_TDR  SCI_TDR4
324 #define RS232_RDR  SCI_RDR4
325 #define RS232_SMR  SCI_SMR4
326 #define RS232_SCMR SCI_SCMR4
327 #define RS232_SCR  SCI_SCR4
328 #define RS232_SSR  SCI_SSR4
329 #define RS232_BRR  SCI_BRR4
330 #define RS232_RXD_PIN ((*DIO_PORT3)&(1<<6))
331
332 #elif 0
333 #define RS232_TDR  SCI_TDR2
334 #define RS232_RDR  SCI_RDR2
335 #define RS232_SMR  SCI_SMR2
336 #define RS232_SCMR SCI_SCMR2
337 #define RS232_SCR  SCI_SCR2
338 #define RS232_SSR  SCI_SSR2
339 #define RS232_BRR  SCI_BRR2
340 #define RS232_RXD_PIN ((*DIO_PORTA)&(1<<2))
341
342 #else
343 #define RS232_TDR  SCI_TDR1
344 #define RS232_RDR  SCI_RDR1
345 #define RS232_SMR  SCI_SMR1
346 #define RS232_SCMR SCI_SCMR1
347 #define RS232_SCR  SCI_SCR1
348 #define RS232_SSR  SCI_SSR1
349 #define RS232_BRR  SCI_BRR1
350 #define RS232_RXD_PIN ((*DIO_PORT3)&(1<<4))
351 #endif
352
353 #define RS232_BAUD_RAW 0xff00
354
355 int SCIInit(unsigned baud)
356 {
357   unsigned divisor;
358   char cks;
359
360   /*disable SCI interrupts and Rx/Tx machine*/
361   *RS232_SCR=0;
362
363   cks=0;
364   if((baud&RS232_BAUD_RAW)!=RS232_BAUD_RAW){
365     divisor=div_us_ulus((CPU_SYS_HZ/16+baud/2),baud);
366     while(divisor>=512){
367       if(++cks>=4) return -1;
368       divisor>>=1;
369     }
370     divisor=(divisor+1)>>1;
371   }else{
372     divisor=baud&0xff;
373   }
374   *RS232_BRR=divisor-1;
375
376   *RS232_SMR=(SMR_CKSxm&cks);
377   *RS232_SCMR=0;
378   FlWait(20000);
379   *RS232_SCR=SCR_TEm|SCR_REm;
380   return 0;
381 }
382
383 volatile int SCISend(unsigned char c)
384 {
385   unsigned int i=50000;
386   while((*RS232_SSR & SSR_TDREm)==0 && i>0) i--;
387   if (i==0) return -1;
388   *RS232_TDR=c;
389   *RS232_SSR=~SSR_TDREm&0xff;
390   return 0;
391 }
392
393 volatile int SCIReceive(unsigned char *c,unsigned int time)
394 {
395   unsigned char ssr;
396   if(time){
397     while(!((ssr=*RS232_SSR) & SSR_RDRFm) && ((time--)>0))
398       if(ssr&(SSR_ORERm|SSR_FERm)) break;
399     if (time==0) return -1;
400   }     
401   else{
402     while(!((ssr=*RS232_SSR) & SSR_RDRFm))
403       if(ssr&(SSR_ORERm|SSR_FERm)) break;
404   }     
405   *c=*RS232_RDR;
406   *RS232_SSR=~(SSR_RDRFm|SSR_MPBTm);
407   if(ssr & (SSR_ORERm|SSR_FERm)){
408     *RS232_SSR=~(SSR_ORERm|SSR_FERm|SSR_MPBTm);
409     return -2;
410   }
411   return 0;
412 }
413
414 unsigned long GetAdr()
415 {
416   unsigned char c;
417   unsigned long a;
418   SCIReceive(&c,0);
419   a=((unsigned long)c << 24);
420   SCIReceive(&c,0);
421   a=a | (((unsigned long)c << 16) & 0xff0000);
422   SCIReceive(&c,0);
423   a=a | (((unsigned long)c << 8) & 0xff00);
424   SCIReceive(&c,0);
425   a=a | ((unsigned long)c & 0xff);
426   SCISend((a >> 24) & 0xFF);
427   SCISend((a >> 16) & 0xFF);
428   SCISend((a >> 8) & 0xFF);
429   SCISend(a & 0xFF);
430   return a;
431 }
432
433 int SCIAutoBaud(void)
434 {
435   int t;
436   unsigned char wtn;
437   
438   /* Disable power-on  reset of WDT owerflow */
439   *WDT_WRSTCSRw=(0x5a00 | 1*WRSTCSR_RSTEm | 0*WRSTCSR_RSTSm);
440   /* Select watchdog function and input clocks  */
441   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm |(1 & WTCSR0_CKSxm));
442   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm | 1*WTCSR0_TMEm | (1 & WTCSR0_CKSxm));
443
444   while(!RS232_RXD_PIN) *WDT_WTCNT0w=(0x5a00);
445   while(RS232_RXD_PIN) *WDT_WTCNT0w=(0x5a00);
446
447   t=0;
448   while(1){
449     wtn=*WDT_WTCNT0r;
450     if(wtn>0xf0){
451       *WDT_WTCNT0w=(0x5a00);
452       t+=0xf0;
453     }
454     if(RS232_RXD_PIN){
455       t+=wtn;
456       break;
457     }
458   };
459
460   /* Disable watchdog */
461   *WDT_WTCSR0w=(0xa500);
462   
463   SCIInit(((t*2+7)/9)|RS232_BAUD_RAW);
464   
465   return t;
466 }
467
468 #ifdef WITH_EXTERNAL_FLASH
469
470 #define EXTFL_addr_mask   0x0ffffl
471 #define EXTFL_reg1_addr   (0x555*2l)
472 #define EXTFL_reg2_addr   (0x2aa*2l)
473 #define EXTFL_sec_size    0x10000 
474 #define EXTFL_width8      0 
475 #define EXTFL_cmd_unlock1 0xaaaa  /* reg1 */
476 #define EXTFL_cmd_unlock2 0x5555  /* reg2 */
477 #define EXTFL_cmd_rdid    0x9090  /* reg1 */
478 #define EXTFL_cmd_prog    0xa0a0  /* reg1 */
479 #define EXTFL_cmd_erase   0x8080  /* reg1 */
480 #define EXTFL_cmd_reset   0xf0f0  /* any */
481 #define EXTFL_erase_all   0x1010  /* reg1 */
482 #define EXTFL_erase_sec   0x3030  /* sector */
483 #define EXTFL_fault_bit   0x2020
484 #define EXTFL_manid       1 
485 #define EXTFL_devid       0x2258
486
487 #define FLASH_WR16(addr,val) (*(volatile __u16*)(addr)=(val))
488 #define FLASH_RD16(addr) (*(volatile __u16*)(addr))
489
490 /* Program data to address */
491 int ExtFlProgRow(__u8 *addr, __u8 *data)
492 {
493   /*FLASH_ROW*/;
494   int ret=0;
495   int cnt=FLASH_ROW/2;
496   __u16 old,new,val;
497   __u32 a=(__u32)addr&~EXTFL_addr_mask;
498   while(cnt--){
499     val=*((__u16*)data)++;
500     /* security sequence */
501     FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
502     FlWait(2);
503     FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
504     FlWait(2);
505     /* program command */
506     FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_prog);
507     FlWait(2);
508     FLASH_WR16(addr,val);
509     FlWait(2);
510     /* wait for result */
511     old=FLASH_RD16(addr);
512     FlWait(2);
513     while((new=FLASH_RD16(addr))!=old){
514       FlWait(2);
515       if((old&EXTFL_fault_bit)&&(new&EXTFL_fault_bit)){
516         if((FLASH_RD16(addr))!=new) ret=-2;
517         break;
518       }
519       old=new;
520     }
521     /* reset */
522     FLASH_WR16(a,EXTFL_cmd_reset);
523     FlWait(2);
524     if(FLASH_RD16(addr)!=val) return -3;
525     ((__u16*)addr)++;
526   }
527   return 0;
528 }
529
530 int ExtFlErase(__u8 *addr)
531 {
532   __u16 old,new;
533   int ret=0;
534   __u32 a=(__u32)addr&~EXTFL_addr_mask;
535   /* security sequence */
536   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
537   FlWait(2);
538   FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
539   FlWait(2);
540   /* erase command */
541   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_erase);
542   FlWait(2);
543   /* security sequence */
544   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
545   FlWait(2);
546   FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
547   FlWait(2);
548   /* select erase range */
549   a=(__u32)addr;
550   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_erase_all);
551   FlWait(2);
552   old=FLASH_RD16(addr);
553   FlWait(2);
554   while((new=FLASH_RD16(addr))!=old){
555     FlWait(2);
556     if((old&EXTFL_fault_bit)&&(new&EXTFL_fault_bit)){
557       if((FLASH_RD16(addr))!=new) ret=-2;
558       break;
559     }
560     old=new;
561   }
562   /* reset */
563   FLASH_WR16(a,EXTFL_cmd_reset);
564   FlWait(2);
565   if(FLASH_RD16(addr)!=0xffff) ret--;    
566   return ret;
567 }
568
569 #endif /*WITH_EXTERNAL_FLASH*/
570
571 void Call(unsigned long adr)
572 {
573   __asm__ /*__volatile__*/(
574          "jsr   @%0\n\t"
575          :
576          :"g" (adr)
577          :"memory","cc");
578 }
579
580 void ProgMode(unsigned baud)
581 {
582   char buf[FLASH_ROW];
583   unsigned long i;
584   unsigned long j;
585   unsigned char e;
586   unsigned char c;
587   unsigned char d;
588   unsigned char cmd;
589   unsigned long badr;
590   unsigned long len;
591   unsigned char *adr;
592   int ret;
593
594   DEB_BLOG_INIT;
595   if(baud) SCIInit(baud);
596   while(1){
597     if(!baud) SCIAutoBaud();
598     SCIReceive(&c,0);
599     while(c!=0x55){
600       SCISend(0);       /*c*/
601       SCIReceive(&c,0);
602     }
603     SCISend(0xAA);
604     SCIReceive(&cmd,0);
605     DEB_WR_HEX(cmd,2); /*!!!*/
606     if((cmd & 7) == (((cmd >> 3) & 7) ^ 7)){
607       SCISend(cmd | 0x80);
608       cmd&=7;
609       if((cmd<=2)||(cmd==4)){
610         /* memory download/upload/erase region */
611         badr=GetAdr();
612         len=GetAdr();
613         if(cmd==0){
614           /* memory download */
615           e=0x5a;
616           i=0;
617           DEB_WR_HEX(badr,8); /*!!!*/
618           DEB_WR_HEX(len,8);  /*!!!*/
619           adr=(unsigned char *)badr;
620           while(i++<len){
621             if(SCIReceive(&c,0)<0){
622               e=0xfd;
623               break;
624             }
625             *adr=c;
626             SCISend(*adr);
627             adr++;
628           }
629           SCISend(e);
630         }
631         else if (cmd==1){
632           /* flash programming */
633           /* check and erase range */
634           /*if(FlPrepBlk(badr,len)<0) e=0xfc;*/
635           i=badr-(badr & 0xffffffe0);
636           j=0;
637           e=0x5a;
638           while((i--)>0){
639             buf[j++]=0xff;
640           }
641           adr=(unsigned char *)(badr & ~(FLASH_ROW-1));
642           j=(unsigned char *)badr-adr;
643           i=0;
644           while(i++<len){
645             if(SCIReceive(&c,0)<0){
646               e=0xfd;
647               j=0;
648               break;
649             }
650             buf[j++]=c;
651             if(j==FLASH_ROW){
652               DEB_WR_HEX((long)adr,6);  /*!!!*/
653               if((ret=FlProgRow(adr,buf))!=0) {
654                 e=-ret;
655                 j=0;
656                 break;
657               }
658               DEB_BLOG(0xEA000000|(__u32)adr|((__u8)j&0x7f));
659               DEB_WR_HEX(j,2);  /*!!!*/
660               adr+=FLASH_ROW;
661               j=0;
662             }
663             SCISend(c);
664           }
665           if(j/*&&!(e&0x80)*/){
666             while(j<FLASH_ROW) buf[j++]=0xff;
667             if((ret=FlProgRow(adr,buf))!=0) e=-ret;
668           }
669           SCISend(e);
670         }else if (cmd==4){
671           /* check and erase region */
672           e=FlPrepBlk(badr,len);
673           if(!e) e=0x5a;
674           SCISend(e);
675         }else{
676           /* upload memory */
677           i=0;
678           e=0x5a;
679           DEB_WR_HEX(badr,8); /*!!!*/
680           DEB_WR_HEX(len,8);  /*!!!*/
681           adr=(unsigned char *)badr;
682           while(i++<len){
683             d=*adr;
684             SCISend(d);
685             if(SCIReceive(&c,0)<0){
686               e=0xfd;
687               break;
688             }
689             if(c!=d) e=0xff;
690             adr++;
691           }
692           SCISend(e);
693         }
694       }else{
695         /* erase block */
696         if(cmd==3){
697           SCIReceive(&c,0);
698           if (c<flash_block_count){
699             if(FlErase(c)==0) SCISend(0x5A);
700                          else SCISend(0xFF);
701          #ifdef WITH_EXTERNAL_FLASH
702           }else if(c==100){
703             if(ExtFlErase((__u8*)EXTERNAL_FLASH_START)==0)
704                SCISend(0x5A); else SCISend(0xFF);
705          #endif /*WITH_EXTERNAL_FLASH*/
706           }else SCISend(0xFE);
707         }
708         else if (cmd==6){
709           badr=GetAdr();
710           DEB_WR_HEX(badr,8); /*!!!*/
711           Call(badr);
712         }
713         else if (cmd==7){
714           wdg_enable(1+1);
715         }
716         else{
717           SCISend(0xFF);
718         }
719       }
720     }else{
721       SCISend(0xFE);
722     }
723   }
724 }