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