]> rtime.felk.cvut.cz Git - sysless.git/blob - arch/h8300/generic/libs/boot/boot_fn.c
Common submodule updated to support USB standard request extensions.
[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\n"
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 -EBOOT_BLNUM_HIGH;
152   if(bl<0) return -EBOOT_BLNUM_LOW;
153
154   if(FlTest(bl)==0) return 0;
155
156   if((*FLM_FLMCR1 & FLMCR1_FWEm)==0) return -EBOOT_NO_FWE;
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 -EBOOT_ERASE_FAILURE;
195   
196  fls_error:
197   *FLM_FLMCR1=0;
198   return -EBOOT_FLASH_ERROR;
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 -EBOOT_ROW_BEGIN;
225   if((*FLM_FLMCR1 & FLMCR1_FWEm)==0 ) return -EBOOT_NO_FWE;
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 -EBOOT_ROW_NOT_ERASED;
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     /* Program-Verify Mode */
254     *FLM_FLMCR1|=FLMCR1_PV1m;
255     FlWait(4);                  /*gamma*/
256     i=0;
257     x=adr;
258     for(i=0;i<FLASH_ROW;i+=2,x+=2){
259       *(__u16*)x=0xffff;
260       FlWait(2);                /*epsilon*/
261       *(__u16*)(prog_data+i)=*(__u16*)x;
262     } 
263     *FLM_FLMCR1&=FLMCR1_SWE1m; /*clear PV1*/
264     FlWait(2);                  /*ny*/
265     if(n<=6){                   /*N1*/
266       x=adr;
267       for(i=0;i<FLASH_ROW;i++,x++){
268         c=prog_data[i]; 
269         d=data[i];
270         if((~c&d)&0xff) goto fls_error;
271         if(c!=d) {
272           m=1;       /* Reprogram needed */
273           /* DEB_BLOG(0xEE000000+(long)x); */
274           /* DEB_BLOG(0xEF000000+(__u16)(c<<8)+(__u8)d); */
275         }
276         *x=d|c;
277         prog_data[i]=d|~c;
278       }
279       
280       FlProgPulse(7);           /*z1<10*/
281       
282     }else{
283       for(i=0;i<FLASH_ROW;i++){
284         c=prog_data[i]; 
285         d=data[i];
286         if(c!=d) m=1; /* Reprogram needed */
287         if((~c&d)&0xff) goto fls_error;
288         prog_data[i]=d|~c;
289       }
290     }
291     if(m==0){
292       *FLM_FLMCR1=0;
293       FlWait(100);              /*x1*/
294       DEB_BLOG(0xED000000+n);
295       return 0;
296     }
297   }
298   *FLM_FLMCR1=0;
299   FlWait(100);                  /*x1*/
300   return -EBOOT_PROG_FAILURE;
301
302  fls_error:
303   *FLM_FLMCR1=0;
304   return -EBOOT_FLASH_VERIFY;
305 }
306
307 int FlPrepBlk(unsigned long badr, unsigned long len)
308 {
309   int bl, blend, res;
310   bl=FlAdr2Blk(badr);
311   blend=FlAdr2Blk(badr+len-1);
312   if((bl<0)||(blend<0)) return -EBOOT_BLOCKADDR;
313   for(;bl<=blend;bl++){
314     if(FlTest(bl)){
315       res=FlErase(bl);
316       if(res<0) return res;
317     }
318   }
319   return 0;
320 }
321
322
323 #if 0
324 #define RS232_TDR  SCI_TDR4
325 #define RS232_RDR  SCI_RDR4
326 #define RS232_SMR  SCI_SMR4
327 #define RS232_SCMR SCI_SCMR4
328 #define RS232_SCR  SCI_SCR4
329 #define RS232_SSR  SCI_SSR4
330 #define RS232_BRR  SCI_BRR4
331 #define RS232_RXD_PIN ((*DIO_PORT3)&(1<<6))
332
333 #elif 0
334 #define RS232_TDR  SCI_TDR2
335 #define RS232_RDR  SCI_RDR2
336 #define RS232_SMR  SCI_SMR2
337 #define RS232_SCMR SCI_SCMR2
338 #define RS232_SCR  SCI_SCR2
339 #define RS232_SSR  SCI_SSR2
340 #define RS232_BRR  SCI_BRR2
341 #define RS232_RXD_PIN ((*DIO_PORTA)&(1<<2))
342
343 #else
344 #define RS232_TDR  SCI_TDR1
345 #define RS232_RDR  SCI_RDR1
346 #define RS232_SMR  SCI_SMR1
347 #define RS232_SCMR SCI_SCMR1
348 #define RS232_SCR  SCI_SCR1
349 #define RS232_SSR  SCI_SSR1
350 #define RS232_BRR  SCI_BRR1
351 #define RS232_RXD_PIN ((*DIO_PORT3)&(1<<4))
352 #endif
353
354 #define RS232_BAUD_RAW 0xff00
355
356 int SCIInit(unsigned baud)
357 {
358   unsigned divisor;
359   char cks;
360
361   /*disable SCI interrupts and Rx/Tx machine*/
362   *RS232_SCR=0;
363
364   cks=0;
365   if((baud&RS232_BAUD_RAW)!=RS232_BAUD_RAW){
366     divisor=div_us_ulus((CPU_SYS_HZ/16+baud/2),baud);
367     while(divisor>=512){
368       if(++cks>=4) return -1;
369       divisor>>=1;
370     }
371     divisor=(divisor+1)>>1;
372   }else{
373     divisor=baud&0xff;
374   }
375   *RS232_BRR=divisor-1;
376
377   *RS232_SMR=(SMR_CKSxm&cks);
378   *RS232_SCMR=0;
379   FlWait(20000);
380   *RS232_SCR=SCR_TEm|SCR_REm;
381   return 0;
382 }
383
384 volatile int SCISend(unsigned char c)
385 {
386   unsigned int i=50000;
387   while((*RS232_SSR & SSR_TDREm)==0 && i>0) i--;
388   if (i==0) return -1;
389   *RS232_TDR=c;
390   *RS232_SSR=~SSR_TDREm&0xff;
391   return 0;
392 }
393
394 volatile int SCIReceive(unsigned char *c,unsigned int time)
395 {
396   unsigned char ssr;
397   if(time){
398     while(!((ssr=*RS232_SSR) & SSR_RDRFm) && ((time--)>0))
399       if(ssr&(SSR_ORERm|SSR_FERm)) break;
400     if (time==0) return -1;
401   }     
402   else{
403     while(!((ssr=*RS232_SSR) & SSR_RDRFm))
404       if(ssr&(SSR_ORERm|SSR_FERm)) break;
405   }     
406   *c=*RS232_RDR;
407   *RS232_SSR=~(SSR_RDRFm|SSR_MPBTm);
408   if(ssr & (SSR_ORERm|SSR_FERm)){
409     *RS232_SSR=~(SSR_ORERm|SSR_FERm|SSR_MPBTm);
410     return -2;
411   }
412   return 0;
413 }
414
415 unsigned long GetAdr()
416 {
417   unsigned char c;
418   unsigned long a;
419   SCIReceive(&c,0);
420   a=((unsigned long)c << 24);
421   SCIReceive(&c,0);
422   a=a | (((unsigned long)c << 16) & 0xff0000);
423   SCIReceive(&c,0);
424   a=a | (((unsigned long)c << 8) & 0xff00);
425   SCIReceive(&c,0);
426   a=a | ((unsigned long)c & 0xff);
427   SCISend((a >> 24) & 0xFF);
428   SCISend((a >> 16) & 0xFF);
429   SCISend((a >> 8) & 0xFF);
430   SCISend(a & 0xFF);
431   return a;
432 }
433
434 int SCIAutoBaud(void)
435 {
436   int t;
437   unsigned char wtn;
438   
439   /* Disable power-on  reset of WDT owerflow */
440   *WDT_WRSTCSRw=(0x5a00 | 1*WRSTCSR_RSTEm | 0*WRSTCSR_RSTSm);
441   /* Select watchdog function and input clocks  */
442   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm |(1 & WTCSR0_CKSxm));
443   *WDT_WTCSR0w=(0xa500 | 1*WTCSR0_WTITm | 1*WTCSR0_TMEm | (1 & WTCSR0_CKSxm));
444
445   while(!RS232_RXD_PIN) *WDT_WTCNT0w=(0x5a00);
446   while(RS232_RXD_PIN) *WDT_WTCNT0w=(0x5a00);
447
448   t=0;
449   while(1){
450     wtn=*WDT_WTCNT0r;
451     if(wtn>0xf0){
452       *WDT_WTCNT0w=(0x5a00);
453       t+=0xf0;
454     }
455     if(RS232_RXD_PIN){
456       t+=wtn;
457       break;
458     }
459   };
460
461   /* Disable watchdog */
462   *WDT_WTCSR0w=(0xa500);
463   
464   SCIInit(((t*2+7)/9)|RS232_BAUD_RAW);
465   
466   return t;
467 }
468
469 #ifdef WITH_EXTERNAL_FLASH
470
471 #define EXTFL_addr_mask   0x0ffffl
472 #define EXTFL_reg1_addr   (0x555*2l)
473 #define EXTFL_reg2_addr   (0x2aa*2l)
474 #define EXTFL_sec_size    0x10000 
475 #define EXTFL_width8      0 
476 #define EXTFL_cmd_unlock1 0xaaaa  /* reg1 */
477 #define EXTFL_cmd_unlock2 0x5555  /* reg2 */
478 #define EXTFL_cmd_rdid    0x9090  /* reg1 */
479 #define EXTFL_cmd_prog    0xa0a0  /* reg1 */
480 #define EXTFL_cmd_erase   0x8080  /* reg1 */
481 #define EXTFL_cmd_reset   0xf0f0  /* any */
482 #define EXTFL_erase_all   0x1010  /* reg1 */
483 #define EXTFL_erase_sec   0x3030  /* sector */
484 #define EXTFL_fault_bit   0x2020
485 #define EXTFL_manid       1 
486 #define EXTFL_devid       0x2258
487
488 #define FLASH_WR16(addr,val) (*(volatile __u16*)(addr)=(val))
489 #define FLASH_RD16(addr) (*(volatile __u16*)(addr))
490
491 /* Program data to address */
492 int ExtFlProgRow(__u8 *addr, __u8 *data)
493 {
494   /*FLASH_ROW*/;
495   int ret=0;
496   int cnt=FLASH_ROW/2;
497   __u16 old,new,val;
498   __u32 a=(__u32)addr&~EXTFL_addr_mask;
499   while(cnt--){
500     val=*((__u16*)data)++;
501     /* security sequence */
502     FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
503     FlWait(2);
504     FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
505     FlWait(2);
506     /* program command */
507     FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_prog);
508     FlWait(2);
509     FLASH_WR16(addr,val);
510     FlWait(2);
511     /* wait for result */
512     old=FLASH_RD16(addr);
513     FlWait(2);
514     while((new=FLASH_RD16(addr))!=old){
515       FlWait(2);
516       if((old&EXTFL_fault_bit)&&(new&EXTFL_fault_bit)){
517         if((FLASH_RD16(addr))!=new) ret=-2;
518         break;
519       }
520       old=new;
521     }
522     /* reset */
523     FLASH_WR16(a,EXTFL_cmd_reset);
524     FlWait(2);
525     if(FLASH_RD16(addr)!=val) return -EBOOT_EXT_FLASH_VERIFY;
526     ((__u16*)addr)++;
527   }
528   return 0;
529 }
530
531 int ExtFlErase(__u8 *addr)
532 {
533   __u16 old,new;
534   int ret=0;
535   __u32 a=(__u32)addr&~EXTFL_addr_mask;
536   /* security sequence */
537   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
538   FlWait(2);
539   FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
540   FlWait(2);
541   /* erase command */
542   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_erase);
543   FlWait(2);
544   /* security sequence */
545   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_cmd_unlock1);
546   FlWait(2);
547   FLASH_WR16(a+EXTFL_reg2_addr,EXTFL_cmd_unlock2);
548   FlWait(2);
549   /* select erase range */
550   a=(__u32)addr;
551   FLASH_WR16(a+EXTFL_reg1_addr,EXTFL_erase_all);
552   FlWait(2);
553   old=FLASH_RD16(addr);
554   FlWait(2);
555   while((new=FLASH_RD16(addr))!=old){
556     FlWait(2);
557     if((old&EXTFL_fault_bit)&&(new&EXTFL_fault_bit)){
558       if((FLASH_RD16(addr))!=new) ret=-2;
559       break;
560     }
561     old=new;
562   }
563   /* reset */
564   FLASH_WR16(a,EXTFL_cmd_reset);
565   FlWait(2);
566   if(FLASH_RD16(addr)!=0xffff) ret--;    
567   return ret;
568 }
569
570 #endif /*WITH_EXTERNAL_FLASH*/
571
572 void Call(unsigned long adr)
573 {
574   __asm__ /*__volatile__*/(
575          "jsr   @%0\n\t"
576          :
577          :"g" (adr)
578          :"memory","cc");
579 }
580
581 void ProgMode(unsigned baud)
582 {
583   char buf[FLASH_ROW];
584   unsigned long i;
585   unsigned long j;
586   unsigned char e;
587   unsigned char c;
588   unsigned char d;
589   unsigned char cmd;
590   unsigned long badr;
591   unsigned long len;
592   unsigned char *adr;
593   int ret;
594
595   DEB_BLOG_INIT;
596   if(baud) SCIInit(baud);
597   while(1){
598     if(!baud) SCIAutoBaud();
599     SCIReceive(&c,0);
600     while(c!=0x55){
601       SCISend(0);       /*c*/
602       SCIReceive(&c,0);
603     }
604     SCISend(0xAA);
605     SCIReceive(&cmd,0);
606     DEB_WR_HEX(cmd,2); /*!!!*/
607     if((cmd & 7) == (((cmd >> 3) & 7) ^ 7)){
608       SCISend(cmd | 0x80);
609       cmd&=7;
610       if((cmd<=2)||(cmd==4)){
611         /* memory download/upload/erase region */
612         badr=GetAdr();
613         len=GetAdr();
614         if(cmd==0){
615           /* memory download */
616           e=0x5a;
617           i=0;
618           DEB_WR_HEX(badr,8); /*!!!*/
619           DEB_WR_HEX(len,8);  /*!!!*/
620           adr=(unsigned char *)badr;
621           while(i++<len){
622             if(SCIReceive(&c,0)<0){
623               e=0xfd;
624               break;
625             }
626             *adr=c;
627             SCISend(*adr);
628             adr++;
629           }
630           SCISend(e);
631         }
632         else if (cmd==1){
633           /* flash programming */
634           /* check and erase range */
635           /*if(FlPrepBlk(badr,len)<0) e=0xfc;*/
636           i=badr-(badr & 0xffffffe0);
637           j=0;
638           e=0x5a;
639           while((i--)>0){
640             buf[j++]=0xff;
641           }
642           adr=(unsigned char *)(badr & ~(FLASH_ROW-1));
643           j=(unsigned char *)badr-adr;
644           i=0;
645           while(i++<len){
646             if(SCIReceive(&c,0)<0){
647               e=0xfd;
648               j=0;
649               break;
650             }
651             buf[j++]=c;
652             if(j==FLASH_ROW){
653               DEB_WR_HEX((long)adr,6);  /*!!!*/
654               if((ret=FlProgRow(adr,buf))!=0) {
655                 e=-ret;
656                 j=0;
657                 break;
658               }
659               DEB_BLOG(0xEA000000|(__u32)adr|((__u8)j&0x7f));
660               DEB_WR_HEX(j,2);  /*!!!*/
661               adr+=FLASH_ROW;
662               j=0;
663             }
664             SCISend(c);
665           }
666           if(j/*&&!(e&0x80)*/){
667             while(j<FLASH_ROW) buf[j++]=0xff;
668             if((ret=FlProgRow(adr,buf))!=0) e=-ret;
669           }
670           SCISend(e);
671         }else if (cmd==4){
672           /* check and erase region */
673           e=FlPrepBlk(badr,len);
674           if(!e) e=0x5a;
675           SCISend(e);
676         }else{
677           /* upload memory */
678           i=0;
679           e=0x5a;
680           DEB_WR_HEX(badr,8); /*!!!*/
681           DEB_WR_HEX(len,8);  /*!!!*/
682           adr=(unsigned char *)badr;
683           while(i++<len){
684             d=*adr;
685             SCISend(d);
686             if(SCIReceive(&c,0)<0){
687               e=0xfd;
688               break;
689             }
690             if(c!=d) e=0xff;
691             adr++;
692           }
693           SCISend(e);
694         }
695       }else{
696         /* erase block */
697         if(cmd==3){
698           SCIReceive(&c,0);
699           if (c<flash_block_count){
700             if(FlErase(c)==0) SCISend(0x5A);
701                          else SCISend(0xFF);
702          #ifdef WITH_EXTERNAL_FLASH
703           }else if(c==100){
704             if(ExtFlErase((__u8*)EXTERNAL_FLASH_START)==0)
705                SCISend(0x5A); else SCISend(0xFF);
706          #endif /*WITH_EXTERNAL_FLASH*/
707           }else SCISend(0xFE);
708         }
709         else if (cmd==6){
710           badr=GetAdr();
711           DEB_WR_HEX(badr,8); /*!!!*/
712           Call(badr);
713         }
714         else if (cmd==7){
715           wdg_enable(1+1);
716         }
717         else{
718           SCISend(0xFF);
719         }
720       }
721     }else{
722       SCISend(0xFE);
723     }
724   }
725 }