]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
* Enable interrupts before starting IH_TYPE_STANDALONE images
authorwdenk <wdenk>
Fri, 25 Jan 2002 00:41:44 +0000 (00:41 +0000)
committerwdenk <wdenk>
Fri, 25 Jan 2002 00:41:44 +0000 (00:41 +0000)
* Flush caches after loading images

12 files changed:
CHANGELOG
common/cmd_boot.c
common/cmd_bootm.c
common/cmd_fdc.c
common/cmd_ide.c
common/cmd_net.c
common/cmd_scsi.c
common/cmd_usb.c
include/ppcboot.h
net/net.c
ppc/Makefile
ppc/cache.c [new file with mode: 0644]

index a5800e99b5ec9f3a08503fc6c45b46cf30661e33..7c1acfde180f3f439ff947605f04130d47ca2028 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,10 @@
 Modifications for 1.1.5:
 ======================================================================
 
+* Enable interrupts before starting IH_TYPE_STANDALONE images
+
+* Flush caches after loading images
+
 * Fix output of "iminfo" for script images
 
 * Include all the 8260 clocks in the "bdinfo" output
index 00242d3b38253fb6b534394deb805071f226bc61..f781b06ab6a52eb85bca28d1a2a912a8afc6ecbe 100644 (file)
@@ -272,8 +272,8 @@ load_serial (ulong offset)
                    }
                    if ((store_addr) < start_addr)
                        start_addr = store_addr;
-                   if ((store_addr+binlen-1) > end_addr)
-                       end_addr = store_addr+binlen-1;
+                   if ((store_addr + binlen - 1) > end_addr)
+                       end_addr = store_addr + binlen - 1;
                    break;
                case SREC_END2:
                case SREC_END3:
@@ -284,9 +284,10 @@ load_serial (ulong offset)
                            "## Last  Load Addr = 0x%08lx\n"
                            "## Total Size      = 0x%08lx = %ld Bytes\n",
                            start_addr, end_addr,
-                           end_addr-start_addr+1,
-                           end_addr-start_addr+1
+                           end_addr - start_addr + 1,
+                           end_addr - start_addr + 1
                    );
+                   flush_cache (addr, end_addr - start_addr + 1);
                    return (addr);
                case SREC_START:
                    break;
@@ -327,7 +328,7 @@ read_record (char *buf, ulong len)
                        *p = c;
                }
 
-           // Check for the console hangup (if any different from serial)
+           /* Check for the console hangup (if any different from serial) */
 
            if (bd_ptr->bi_mon_fnc->getc != serial_getc)
            {
@@ -456,78 +457,78 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *ar
 }
 
 
-static ulong
-load_serial_bin (ulong offset)
+static ulong load_serial_bin (ulong offset)
 {
-  set_kerm_bin_mode((ulong *)offset);
-  k_recv();
-  return offset;
+       int size;
+
+       set_kerm_bin_mode ((ulong *) offset);
+       size = k_recv ();
+       flush_cache (offset, size);
+       return offset;
 }
 
-void send_pad(void)
+void send_pad (void)
 {
-   int count = his_pad_count;
-   while (count-- > 0) serial_putc(his_pad_char);
+       int count = his_pad_count;
+
+       while (count-- > 0)
+               serial_putc (his_pad_char);
 }
 
 /* converts escaped kermit char to binary char */
-char ktrans(char in)
+char ktrans (char in)
 {
-   if ((in & 0x60) == 0x40)
-   {
-      return (char) (in & ~0x40);
-   }
-   else if ((in & 0x7f) == 0x3f)
-   {
-      return (char) (in | 0x40);
-   }
-   else return in;
+       if ((in & 0x60) == 0x40) {
+               return (char) (in & ~0x40);
+       } else if ((in & 0x7f) == 0x3f) {
+               return (char) (in | 0x40);
+       } else
+               return in;
 }
 
-int chk1(char *buffer)
+int chk1 (char *buffer)
 {
-   int total = 0;
-   while (*buffer)
-   {
-      total += *buffer++;
-   }
-   return (int) ((total + ((total  >> 6) & 0x03)) & 0x3f);
+       int total = 0;
+
+       while (*buffer) {
+               total += *buffer++;
+       }
+       return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
 }
 
-void s1_sendpacket(char *packet)
+void s1_sendpacket (char *packet)
 {
-   send_pad();
-   while (*packet)
-   {
-      serial_putc(*packet++);
-   }
+       send_pad ();
+       while (*packet) {
+               serial_putc (*packet++);
+       }
 }
 
 static char a_b[24];
-void send_ack(int n)
+void send_ack (int n)
 {
-   a_b[0] = START_CHAR;
-   a_b[1] = tochar(3);
-   a_b[2] = tochar(n);
-   a_b[3] = ACK_TYPE;
-   a_b[4] = '\0';
-   a_b[4] = tochar(chk1(&a_b[1]));
-   a_b[5] = his_eol;
-   a_b[6] = '\0';
-   s1_sendpacket(a_b);
+       a_b[0] = START_CHAR;
+       a_b[1] = tochar (3);
+       a_b[2] = tochar (n);
+       a_b[3] = ACK_TYPE;
+       a_b[4] = '\0';
+       a_b[4] = tochar (chk1 (&a_b[1]));
+       a_b[5] = his_eol;
+       a_b[6] = '\0';
+       s1_sendpacket (a_b);
 }
 
-void send_nack(int n)
+void send_nack (int n)
 {
-   a_b[0] = START_CHAR;
-   a_b[1] = tochar(3);
-   a_b[2] = tochar(n);
-   a_b[3] = NACK_TYPE;
-   a_b[4] = '\0';
-   a_b[4] = tochar(chk1(&a_b[1]));
-   a_b[5] = his_eol;
-   a_b[6] = '\0';
-   s1_sendpacket(a_b);
+       a_b[0] = START_CHAR;
+       a_b[1] = tochar (3);
+       a_b[2] = tochar (n);
+       a_b[3] = NACK_TYPE;
+       a_b[4] = '\0';
+       a_b[4] = tochar (chk1 (&a_b[1]));
+       a_b[5] = his_eol;
+       a_b[6] = '\0';
+       s1_sendpacket (a_b);
 }
 
 
@@ -537,94 +538,87 @@ void send_nack(int n)
 
    if image is binary, no header is stored in os_data_header.
 */
-void (*os_data_init)(void);
-void (*os_data_char)(char new_char);
+void (*os_data_init) (void);
+void (*os_data_char) (char new_char);
 static int os_data_state, os_data_state_saved;
 int os_data_count;
 static int os_data_count_saved;
 static char *os_data_addr, *os_data_addr_saved;
 static char *bin_start_address;
 int os_data_header[8];
-void image_data_init(void)
+void image_data_init (void)
 {
-   os_data_state = 0;
-   os_data_count = 32;
-   os_data_addr = (char *) os_data_header;
+       os_data_state = 0;
+       os_data_count = 32;
+       os_data_addr = (char *) os_data_header;
 }
-void bin_data_init(void)
+void bin_data_init (void)
 {
-   os_data_state = 0;
-   os_data_count = 0;
-   os_data_addr = bin_start_address;
+       os_data_state = 0;
+       os_data_count = 0;
+       os_data_addr = bin_start_address;
 }
-void os_data_save(void)
+void os_data_save (void)
 {
-   os_data_state_saved = os_data_state;
-   os_data_count_saved = os_data_count;
-   os_data_addr_saved = os_data_addr;
+       os_data_state_saved = os_data_state;
+       os_data_count_saved = os_data_count;
+       os_data_addr_saved = os_data_addr;
 }
-void os_data_restore(void)
+void os_data_restore (void)
 {
-   os_data_state = os_data_state_saved;
-   os_data_count = os_data_count_saved;
-   os_data_addr = os_data_addr_saved;
+       os_data_state = os_data_state_saved;
+       os_data_count = os_data_count_saved;
+       os_data_addr = os_data_addr_saved;
 }
-void bin_data_char(char new_char)
+void bin_data_char (char new_char)
 {
-   switch (os_data_state)
-   {
-      case 0: /* data */
-         *os_data_addr++ = new_char;
-         --os_data_count;
-         break;
-   }
+       switch (os_data_state) {
+       case 0:                                 /* data */
+               *os_data_addr++ = new_char;
+               --os_data_count;
+               break;
+       }
 }
-void set_kerm_bin_mode(unsigned long *addr)
+void set_kerm_bin_mode (unsigned long *addr)
 {
-   bin_start_address = (char *) addr;
-   os_data_init = bin_data_init;
-   os_data_char = bin_data_char;
+       bin_start_address = (char *) addr;
+       os_data_init = bin_data_init;
+       os_data_char = bin_data_char;
 }
 
 
 /* k_data_* simply handles the kermit escape translations */
 static int k_data_escape, k_data_escape_saved;
-void k_data_init(void)
+void k_data_init (void)
 {
-   k_data_escape = 0;
-   os_data_init();
+       k_data_escape = 0;
+       os_data_init ();
 }
-void k_data_save(void)
+void k_data_save (void)
 {
-   k_data_escape_saved = k_data_escape;
-   os_data_save();
+       k_data_escape_saved = k_data_escape;
+       os_data_save ();
 }
-void k_data_restore(void)
+void k_data_restore (void)
 {
-   k_data_escape = k_data_escape_saved;
-   os_data_restore();
+       k_data_escape = k_data_escape_saved;
+       os_data_restore ();
 }
-void k_data_char(char new_char)
+void k_data_char (char new_char)
 {
-   if (k_data_escape)
-   {
-      /* last char was escape - translate this character */
-      os_data_char(ktrans(new_char));
-      k_data_escape = 0;
-   }
-   else
-   {
-      if (new_char == his_quote)
-      {
-         /* this char is escape - remember */
-         k_data_escape = 1;
-      }
-      else
-      {
-         /* otherwise send this char as-is */
-         os_data_char(new_char);
-      }
-   }
+       if (k_data_escape) {
+               /* last char was escape - translate this character */
+               os_data_char (ktrans (new_char));
+               k_data_escape = 0;
+       } else {
+               if (new_char == his_quote) {
+                       /* this char is escape - remember */
+                       k_data_escape = 1;
+               } else {
+                       /* otherwise send this char as-is */
+                       os_data_char (new_char);
+               }
+       }
 }
 
 #define SEND_DATA_SIZE  20
@@ -633,252 +627,258 @@ char *send_ptr;
 
 /* handle_send_packet interprits the protocol info and builds and
    sends an appropriate ack for what we can do */
-void handle_send_packet(int n)
+void handle_send_packet (int n)
 {
-   int length = 3;
-   int bytes;
-
-   /* initialize some protocol parameters */
-   his_eol = END_CHAR; /* default end of line character */
-   his_pad_count = 0;
-   his_pad_char = '\0';
-   his_quote = K_ESCAPE;
-
-   /* ignore last character if it filled the buffer */
-   if (send_ptr == &send_parms[SEND_DATA_SIZE - 1]) --send_ptr;
-   bytes = send_ptr - send_parms; /* how many bytes we'll process */
-   do
-   {
-      if (bytes-- <= 0) break;
-      /* handle MAXL - max length */
-      /* ignore what he says - most I'll take (here) is 94 */
-      a_b[++length] = tochar(94);
-      if (bytes-- <= 0) break;
-      /* handle TIME - time you should wait for my packets */
-      /* ignore what he says - don't wait for my ack longer than 1 second */
-      a_b[++length] = tochar(1);
-      if (bytes-- <= 0) break;
-      /* handle NPAD - number of pad chars I need */
-      /* remember what he says - I need none */
-      his_pad_count = untochar(send_parms[2]);
-      a_b[++length] = tochar(0);
-      if (bytes-- <= 0) break;
-      /* handle PADC - pad chars I need */
-      /* remember what he says - I need none */
-      his_pad_char = ktrans(send_parms[3]);
-      a_b[++length] = 0x40; /* He should ignore this */
-      if (bytes-- <= 0) break;
-      /* handle EOL - end of line he needs */
-      /* remember what he says - I need CR */
-      his_eol = untochar(send_parms[4]);
-      a_b[++length] = tochar(END_CHAR);
-      if (bytes-- <= 0) break;
-      /* handle QCTL - quote control char he'll use */
-      /* remember what he says - I'll use '#' */
-      his_quote = send_parms[5];
-      a_b[++length] = '#';
-      if (bytes-- <= 0) break;
-      /* handle QBIN - 8-th bit prefixing */
-      /* ignore what he says - I refuse */
-      a_b[++length] = 'N';
-      if (bytes-- <= 0) break;
-      /* handle CHKT - the clock check type */
-      /* ignore what he says - I do type 1 (for now) */
-      a_b[++length] = '1';
-      if (bytes-- <= 0) break;
-      /* handle REPT - the repeat prefix */
-      /* ignore what he says - I refuse (for now) */
-      a_b[++length] = 'N';
-      if (bytes-- <= 0) break;
-      /* handle CAPAS - the capabilities mask */
-      /* ignore what he says - I only do long packets - I don't do windows */
-      a_b[++length] = tochar(2); /* only long packets */
-      a_b[++length] = tochar(0); /* no windows */
-      a_b[++length] = tochar(94); /* large packet msb */
-      a_b[++length] = tochar(94); /* large packet lsb */
-   } while (0);
-
-   a_b[0] = START_CHAR;
-   a_b[1] = tochar(length);
-   a_b[2] = tochar(n);
-   a_b[3] = ACK_TYPE;
-   a_b[++length] = '\0';
-   a_b[length] = tochar(chk1(&a_b[1]));
-   a_b[++length] = his_eol;
-   a_b[++length] = '\0';
-   s1_sendpacket(a_b);
+       int length = 3;
+       int bytes;
+
+       /* initialize some protocol parameters */
+       his_eol = END_CHAR;             /* default end of line character */
+       his_pad_count = 0;
+       his_pad_char = '\0';
+       his_quote = K_ESCAPE;
+
+       /* ignore last character if it filled the buffer */
+       if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
+               --send_ptr;
+       bytes = send_ptr - send_parms;  /* how many bytes we'll process */
+       do {
+               if (bytes-- <= 0)
+                       break;
+               /* handle MAXL - max length */
+               /* ignore what he says - most I'll take (here) is 94 */
+               a_b[++length] = tochar (94);
+               if (bytes-- <= 0)
+                       break;
+               /* handle TIME - time you should wait for my packets */
+               /* ignore what he says - don't wait for my ack longer than 1 second */
+               a_b[++length] = tochar (1);
+               if (bytes-- <= 0)
+                       break;
+               /* handle NPAD - number of pad chars I need */
+               /* remember what he says - I need none */
+               his_pad_count = untochar (send_parms[2]);
+               a_b[++length] = tochar (0);
+               if (bytes-- <= 0)
+                       break;
+               /* handle PADC - pad chars I need */
+               /* remember what he says - I need none */
+               his_pad_char = ktrans (send_parms[3]);
+               a_b[++length] = 0x40;   /* He should ignore this */
+               if (bytes-- <= 0)
+                       break;
+               /* handle EOL - end of line he needs */
+               /* remember what he says - I need CR */
+               his_eol = untochar (send_parms[4]);
+               a_b[++length] = tochar (END_CHAR);
+               if (bytes-- <= 0)
+                       break;
+               /* handle QCTL - quote control char he'll use */
+               /* remember what he says - I'll use '#' */
+               his_quote = send_parms[5];
+               a_b[++length] = '#';
+               if (bytes-- <= 0)
+                       break;
+               /* handle QBIN - 8-th bit prefixing */
+               /* ignore what he says - I refuse */
+               a_b[++length] = 'N';
+               if (bytes-- <= 0)
+                       break;
+               /* handle CHKT - the clock check type */
+               /* ignore what he says - I do type 1 (for now) */
+               a_b[++length] = '1';
+               if (bytes-- <= 0)
+                       break;
+               /* handle REPT - the repeat prefix */
+               /* ignore what he says - I refuse (for now) */
+               a_b[++length] = 'N';
+               if (bytes-- <= 0)
+                       break;
+               /* handle CAPAS - the capabilities mask */
+               /* ignore what he says - I only do long packets - I don't do windows */
+               a_b[++length] = tochar (2);     /* only long packets */
+               a_b[++length] = tochar (0);     /* no windows */
+               a_b[++length] = tochar (94);    /* large packet msb */
+               a_b[++length] = tochar (94);    /* large packet lsb */
+       } while (0);
+
+       a_b[0] = START_CHAR;
+       a_b[1] = tochar (length);
+       a_b[2] = tochar (n);
+       a_b[3] = ACK_TYPE;
+       a_b[++length] = '\0';
+       a_b[length] = tochar (chk1 (&a_b[1]));
+       a_b[++length] = his_eol;
+       a_b[++length] = '\0';
+       s1_sendpacket (a_b);
 }
 
 /* k_recv receives a OS Open image file over kermit line */
-int k_recv(void)
+int k_recv (void)
 {
-   char new_char;
-   char k_state, k_state_saved;
-   int sum;
-   int done;
-   int length;
-   int n, last_n;
-   int z = 0;
-   int len_lo, len_hi;
-
-   /* initialize some protocol parameters */
-   his_eol = END_CHAR; /* default end of line character */
-   his_pad_count = 0;
-   his_pad_char = '\0';
-   his_quote = K_ESCAPE;
-
-   /* initialize the k_recv and k_data state machine */
-   done = 0;
-   k_state = 0;
-   k_data_init();
-   k_state_saved = k_state;
-   k_data_save();
-   n = 0; /* just to get rid of a warning */
-   last_n = -1;
-
-   /* expect this "type" sequence (but don't check):
-      S: send initiate
-      F: file header
-      D: data (multiple)
-      Z: end of file
-      B: break transmission
-   */
-
-   /* enter main loop */
-   while (!done)
-   {
-      /* set the send packet pointer to begining of send packet parms */
-      send_ptr = send_parms;
-
-      /* With each packet, start summing the bytes starting with the length.
-         Save the current sequence number.
-         Note the type of the packet.
-         If a character less than SPACE (0x20) is received - error.
-      */
+       char new_char;
+       char k_state, k_state_saved;
+       int sum;
+       int done;
+       int length;
+       int n, last_n;
+       int z = 0;
+       int len_lo, len_hi;
+
+       /* initialize some protocol parameters */
+       his_eol = END_CHAR;             /* default end of line character */
+       his_pad_count = 0;
+       his_pad_char = '\0';
+       his_quote = K_ESCAPE;
+
+       /* initialize the k_recv and k_data state machine */
+       done = 0;
+       k_state = 0;
+       k_data_init ();
+       k_state_saved = k_state;
+       k_data_save ();
+       n = 0;                          /* just to get rid of a warning */
+       last_n = -1;
+
+       /* expect this "type" sequence (but don't check):
+          S: send initiate
+          F: file header
+          D: data (multiple)
+          Z: end of file
+          B: break transmission
+        */
+
+       /* enter main loop */
+       while (!done) {
+               /* set the send packet pointer to begining of send packet parms */
+               send_ptr = send_parms;
+
+               /* With each packet, start summing the bytes starting with the length.
+                  Save the current sequence number.
+                  Note the type of the packet.
+                  If a character less than SPACE (0x20) is received - error.
+                */
 
 #if 0
-      /* OLD CODE, Prior to checking sequence numbers */
-      /* first have all state machines save current states */
-      k_state_saved = k_state;
-      k_data_save();
+               /* OLD CODE, Prior to checking sequence numbers */
+               /* first have all state machines save current states */
+               k_state_saved = k_state;
+               k_data_save ();
 #endif
 
-      /* get a packet */
-      /* wait for the starting character */
-      while (serial_getc() != START_CHAR);
-      /* get length of packet */
-      sum = 0;
-      new_char = serial_getc();
-      if ((new_char & 0xE0) == 0) goto packet_error;
-      sum += new_char & 0xff;
-      length = untochar(new_char);
-      /* get sequence number */
-      new_char = serial_getc();
-      if ((new_char & 0xE0) == 0) goto packet_error;
-      sum += new_char & 0xff;
-      n = untochar(new_char);
-      --length;
-
-      /* NEW CODE - check sequence numbers for retried packets */
-      /* Note - this new code assumes that the sequence number is correctly
-         received.  Handling an invalid sequence number adds another layer
-         of complexity that may not be needed - yet!  At this time, I'm hoping
-         that I don't need to buffer the incoming data packets and can write
-         the data into memory in real time.  */
-      if (n == last_n)
-      {
-         /* same sequence number, restore the previous state */
-         k_state = k_state_saved;
-         k_data_restore();
-      }
-      else
-      {
-         /* new sequence number, checkpoint the download */
-         last_n = n;
-         k_state_saved = k_state;
-         k_data_save();
-      }
-      /* END NEW CODE */
-
-      /* get packet type */
-      new_char = serial_getc();
-      if ((new_char & 0xE0) == 0) goto packet_error;
-      sum += new_char & 0xff;
-      k_state = new_char;
-      --length;
-      /* check for extended length */
-      if (length == -2)
-      {
-         /* (length byte was 0, decremented twice) */
-         /* get the two length bytes */
-         new_char = serial_getc();
-         if ((new_char & 0xE0) == 0) goto packet_error;
-         sum += new_char & 0xff;
-         len_hi = untochar(new_char);
-         new_char = serial_getc();
-         if ((new_char & 0xE0) == 0) goto packet_error;
-         sum += new_char & 0xff;
-         len_lo = untochar(new_char);
-         length = len_hi * 95 + len_lo;
-         /* check header checksum */
-         new_char = serial_getc();
-         if ((new_char & 0xE0) == 0) goto packet_error;
-         if (new_char != tochar((sum + ((sum  >> 6) & 0x03)) & 0x3f))
-            goto packet_error;
-         sum += new_char & 0xff;
-         /* --length; *//* new length includes only data and block check to come */
-      }
-      /* bring in rest of packet */
-      while (length > 1)
-      {
-         new_char = serial_getc();
-         if ((new_char & 0xE0) == 0) goto packet_error;
-         sum += new_char & 0xff;
-         --length;
-         if (k_state == DATA_TYPE)
-         {
-            /* pass on the data if this is a data packet */
-            k_data_char(new_char);
-         }
-         else if (k_state == SEND_TYPE)
-         {
-            /* save send pack in buffer as is */
-            *send_ptr++ = new_char;
-            /* if too much data, back off the pointer */
-            if (send_ptr >= &send_parms[SEND_DATA_SIZE]) --send_ptr;
-         }
-      }
-      /* get and validate checksum character */
-      new_char = serial_getc();
-      if ((new_char & 0xE0) == 0) goto packet_error;
-      if (new_char != tochar((sum + ((sum  >> 6) & 0x03)) & 0x3f))
-         goto packet_error;
-      /* get END_CHAR */
-      new_char = serial_getc();
-      if (new_char != END_CHAR)
-      {
-packet_error:
-         /* restore state machines */
-         k_state = k_state_saved;
-         k_data_restore();
-         /* send a negative acknowledge packet in */
-         send_nack(n);
-      }
-      else if (k_state == SEND_TYPE)
-      {
-         /* crack the protocol parms, build an appropriate ack packet */
-         handle_send_packet(n);
-      }
-      else
-      {
-         /* send simple acknowledge packet in */
-         send_ack(n);
-         /* quit if end of transmission */
-         if (k_state == BREAK_TYPE) done = 1;
-      }
-      ++z;
-   }
-   return 0;
+               /* get a packet */
+               /* wait for the starting character */
+               while (serial_getc () != START_CHAR);
+               /* get length of packet */
+               sum = 0;
+               new_char = serial_getc ();
+               if ((new_char & 0xE0) == 0)
+                       goto packet_error;
+               sum += new_char & 0xff;
+               length = untochar (new_char);
+               /* get sequence number */
+               new_char = serial_getc ();
+               if ((new_char & 0xE0) == 0)
+                       goto packet_error;
+               sum += new_char & 0xff;
+               n = untochar (new_char);
+               --length;
+
+               /* NEW CODE - check sequence numbers for retried packets */
+               /* Note - this new code assumes that the sequence number is correctly
+                * received.  Handling an invalid sequence number adds another layer
+                * of complexity that may not be needed - yet!  At this time, I'm hoping
+                * that I don't need to buffer the incoming data packets and can write
+                * the data into memory in real time.
+                */
+               if (n == last_n) {
+                       /* same sequence number, restore the previous state */
+                       k_state = k_state_saved;
+                       k_data_restore ();
+               } else {
+                       /* new sequence number, checkpoint the download */
+                       last_n = n;
+                       k_state_saved = k_state;
+                       k_data_save ();
+               }
+               /* END NEW CODE */
+
+               /* get packet type */
+               new_char = serial_getc ();
+               if ((new_char & 0xE0) == 0)
+                       goto packet_error;
+               sum += new_char & 0xff;
+               k_state = new_char;
+               --length;
+               /* check for extended length */
+               if (length == -2) {
+                       /* (length byte was 0, decremented twice) */
+                       /* get the two length bytes */
+                       new_char = serial_getc ();
+                       if ((new_char & 0xE0) == 0)
+                               goto packet_error;
+                       sum += new_char & 0xff;
+                       len_hi = untochar (new_char);
+                       new_char = serial_getc ();
+                       if ((new_char & 0xE0) == 0)
+                               goto packet_error;
+                       sum += new_char & 0xff;
+                       len_lo = untochar (new_char);
+                       length = len_hi * 95 + len_lo;
+                       /* check header checksum */
+                       new_char = serial_getc ();
+                       if ((new_char & 0xE0) == 0)
+                               goto packet_error;
+                       if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
+                               goto packet_error;
+                       sum += new_char & 0xff;
+/* --length; *//* new length includes only data and block check to come */
+               }
+               /* bring in rest of packet */
+               while (length > 1) {
+                       new_char = serial_getc ();
+                       if ((new_char & 0xE0) == 0)
+                               goto packet_error;
+                       sum += new_char & 0xff;
+                       --length;
+                       if (k_state == DATA_TYPE) {
+                               /* pass on the data if this is a data packet */
+                               k_data_char (new_char);
+                       } else if (k_state == SEND_TYPE) {
+                               /* save send pack in buffer as is */
+                               *send_ptr++ = new_char;
+                               /* if too much data, back off the pointer */
+                               if (send_ptr >= &send_parms[SEND_DATA_SIZE])
+                                       --send_ptr;
+                       }
+               }
+               /* get and validate checksum character */
+               new_char = serial_getc ();
+               if ((new_char & 0xE0) == 0)
+                       goto packet_error;
+               if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
+                       goto packet_error;
+               /* get END_CHAR */
+               new_char = serial_getc ();
+               if (new_char != END_CHAR) {
+                 packet_error:
+                       /* restore state machines */
+                       k_state = k_state_saved;
+                       k_data_restore ();
+                       /* send a negative acknowledge packet in */
+                       send_nack (n);
+               } else if (k_state == SEND_TYPE) {
+                       /* crack the protocol parms, build an appropriate ack packet */
+                       handle_send_packet (n);
+               } else {
+                       /* send simple acknowledge packet in */
+                       send_ack (n);
+                       /* quit if end of transmission */
+                       if (k_state == BREAK_TYPE)
+                               done = 1;
+               }
+               ++z;
+       }
+       return ((ulong) os_data_addr - (ulong) bin_start_address);
 }
-
 #endif /* CFG_CMD_LOADB */
index 4bc4f1d7ca6fce5305cb3837774df0dd61596d76..7cc000ec6d0567b6820534ced382174ef170d9da 100644 (file)
@@ -206,11 +206,10 @@ int do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        switch (hdr->ih_type) {
        case IH_TYPE_STANDALONE:
                appl = (int (*)(cmd_tbl_t *, bd_t *, int, int, char *[]))hdr->ih_ep;
-
-               (*appl)(cmdtp, bd, flag, argc-1, &argv[1]);
-               /* just in case we return */
                if (iflag)
                        enable_interrupts();
+
+               (*appl)(cmdtp, bd, flag, argc-1, &argv[1]);
                break;
        case IH_TYPE_KERNEL:
        case IH_TYPE_MULTI:
index 3f5620661cfe19d07d287cb70bc1113a5d786c9a..c1885c5208ec974ddf393da0cfda301543f8dc07 100644 (file)
@@ -705,6 +705,8 @@ int do_fdcboot(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                return 1;
        }
        printf("OK %ld Bytes loaded.\n",imsize);
+
+       flush_cache (addr, imsize);
        /* Loading ok, update default load address */
 
        load_addr = addr;
index a29d7f6bece48ac50a7d242a76818a2639ebe5f1..9097614d6df76bc1e35edfeca395ce88009b3abe 100644 (file)
@@ -285,6 +285,9 @@ int do_ide (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                n = ide_dev_desc[curr_device].block_read (curr_device,
                                                          blk, cnt,
                                                          (ulong *)addr);
+               /* flush cache after read */
+               flush_cache (addr, cnt*ide_dev_desc[curr_device].blksz);
+
                printf ("%ld blocks read: %s\n",
                        n, (n==cnt) ? "OK" : "ERROR");
                if (n==cnt) {
index 64bcd8fad84404785e5e7bf563e778de95eb4165..ac5ed27005f09e20ee877fa31352e16546a2c919 100644 (file)
@@ -101,6 +101,7 @@ netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[])
 {
        char *s;
        int   rcode = 0;
+       int   size;
 
        switch (argc) {
        case 1:
@@ -126,12 +127,15 @@ netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[])
                return 1;
        }
 
-       if (NetLoop(bd, proto) == 0)
+       if ((size = NetLoop(bd, proto)) == 0)
                return 1;
 
        /* NetLoop ok, update environment */
        netboot_update_env();
 
+       /* flush cache */
+       flush_cache(load_addr, size);
+
        /* Loading ok, check if we should attempt an auto-start */
        if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
                char *local_args[2];
index 1235de940c80ff807252be2d8f3207afe8c144b3..b0b3f9664d4fba7de9c150b9e8a965a0f4fa9be9 100644 (file)
@@ -308,6 +308,9 @@ int do_scsiboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        }
        /* Loading ok, update default load address */
        load_addr = addr;
+
+       flush_cache (addr, (cnt+1)*info.blksz);
+
        /* Check if we should attempt an auto-start */
        if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
                char *local_args[2];
index ce432bd95f29053cee7ebba7fac5f4627e5dcab8..f9ab48355dc6b78fb2e10e1b439933c386bd355f 100644 (file)
@@ -46,25 +46,25 @@ static int usb_stor_curr_dev=-1; /* current device */
 char * usb_get_class_desc(unsigned char dclass)
 {
        switch(dclass) {
-               case USB_CLASS_PER_INTERFACE: 
-                       return("See Interface"); 
-               case USB_CLASS_AUDIO: 
+               case USB_CLASS_PER_INTERFACE:
+                       return("See Interface");
+               case USB_CLASS_AUDIO:
                        return("Audio");
-               case USB_CLASS_COMM: 
+               case USB_CLASS_COMM:
                        return("Communication");
-               case USB_CLASS_HID: 
+               case USB_CLASS_HID:
                        return("Human Interface");
-               case USB_CLASS_PRINTER: 
+               case USB_CLASS_PRINTER:
                        return("Printer");
-               case USB_CLASS_MASS_STORAGE: 
+               case USB_CLASS_MASS_STORAGE:
                        return("Mass Storage");
-               case USB_CLASS_HUB: 
+               case USB_CLASS_HUB:
                        return("Hub");
-               case USB_CLASS_DATA: 
+               case USB_CLASS_DATA:
                        return("CDC Data");
-               case USB_CLASS_VENDOR_SPEC: 
+               case USB_CLASS_VENDOR_SPEC:
                        return("Vendor specific");
-               default : 
+               default :
                        return("");
        }
 }
@@ -72,9 +72,9 @@ char * usb_get_class_desc(unsigned char dclass)
 void usb_display_class_sub(unsigned char dclass,unsigned char subclass,unsigned char proto)
 {
        switch(dclass) {
-               case USB_CLASS_PER_INTERFACE: 
+               case USB_CLASS_PER_INTERFACE:
                        printf("See Interface");
-                       break; 
+                       break;
                case USB_CLASS_HID:
                        printf("Human Interface, Subclass: ");
                        switch(subclass) {
@@ -149,20 +149,20 @@ void usb_display_class_sub(unsigned char dclass,unsigned char subclass,unsigned
 void usb_display_string(struct usb_device *dev,int index)
 {
        char buffer[256];
-       if(index!=0) {
-               if(usb_string(dev,index,&buffer[0],256)>0);
+       if (index!=0) {
+               if (usb_string(dev,index,&buffer[0],256)>0);
                        printf("String: \"%s\"",buffer);
        }
 }
 
 void usb_display_desc(struct usb_device *dev)
 {
-       if(dev->descriptor.bDescriptorType==USB_DT_DEVICE) {
+       if (dev->descriptor.bDescriptorType==USB_DT_DEVICE) {
                printf("%d: %s,  USB Revision %x.%x\n",dev->devnum,usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
                        (dev->descriptor.bcdUSB>>8) & 0xff,dev->descriptor.bcdUSB & 0xff);
-               if(strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
+               if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
                        printf(" - %s %s %s\n",dev->mf,dev->prod,dev->serial);
-               if(dev->descriptor.bDeviceClass) {
+               if (dev->descriptor.bDeviceClass) {
                        printf(" - Class: ");
                        usb_display_class_sub(dev->descriptor.bDeviceClass,dev->descriptor.bDeviceSubClass,dev->descriptor.bDeviceProtocol);
                        printf("\n");
@@ -170,10 +170,10 @@ void usb_display_desc(struct usb_device *dev)
                else {
                        printf(" - Class: (from Interface) %s\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass));
                }
-               printf(" - PacketSize: %d  Configurations: %d\n",dev->descriptor.bMaxPacketSize0,dev->descriptor.bNumConfigurations);           
+               printf(" - PacketSize: %d  Configurations: %d\n",dev->descriptor.bMaxPacketSize0,dev->descriptor.bNumConfigurations);
                printf(" - Vendor: 0x%04x  Product 0x%04x Version %d.%d\n",dev->descriptor.idVendor,dev->descriptor.idProduct,(dev->descriptor.bcdDevice>>8) & 0xff,dev->descriptor.bcdDevice & 0xff);
        }
-       
+
 }
 
 void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_device *dev)
@@ -181,7 +181,7 @@ void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_devic
        printf("   Configuration: %d\n",config->bConfigurationValue);
        printf("   - Interfaces: %d %s%s%dmA\n",config->bNumInterfaces,(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
        (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",config->MaxPower*2);
-       if(config->iConfiguration) {
+       if (config->iConfiguration) {
                printf("   - ");
                usb_display_string(dev,config->iConfiguration);
                printf("\n");
@@ -195,7 +195,7 @@ void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,struct usb_devi
        printf("     - Class ");
        usb_display_class_sub(ifdesc->bInterfaceClass,ifdesc->bInterfaceSubClass,ifdesc->bInterfaceProtocol);
        printf("\n");
-       if(ifdesc->iInterface) {
+       if (ifdesc->iInterface) {
                printf("     - ");
                usb_display_string(dev,ifdesc->iInterface);
                printf("\n");
@@ -213,7 +213,7 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
                case 3: printf("Interrupt"); break;
        }
        printf(" MaxPacket %d",epdesc->wMaxPacketSize);
-       if((epdesc->bmAttributes & 0x03)==0x3)
+       if ((epdesc->bmAttributes & 0x03)==0x3)
                printf(" Interval %dms",epdesc->bInterval);
        printf("\n");
 }
@@ -244,25 +244,25 @@ void usb_show_tree_graph(struct usb_device *dev,char *pre)
 {
        int i,index;
        int has_child,last_child,port;
-       
+
        index=strlen(pre);
        printf(" %s",pre);
        /* check if the device has connected children */
        has_child=0;
        for(i=0;i<dev->maxchild;i++) {
-               if(dev->children[i]!=NULL)
+               if (dev->children[i]!=NULL)
                        has_child=1;
        }
        /* check if we are the last one */
        last_child=1;
-       if(dev->parent!=NULL) {
+       if (dev->parent!=NULL) {
                for(i=0;i<dev->parent->maxchild;i++) {
                        /* search for children */
-                       if(dev->parent->children[i]==dev) { 
+                       if (dev->parent->children[i]==dev) {
                                /* found our pointer, see if we have a little sister */
                                port=i;
                                while(i++<dev->parent->maxchild) {
-                                       if(dev->parent->children[i]!=NULL) {
+                                       if (dev->parent->children[i]!=NULL) {
                                                /* found a sister */
                                                last_child=0;
                                                break;
@@ -272,7 +272,7 @@ void usb_show_tree_graph(struct usb_device *dev,char *pre)
                } /* for all children of the parent */
                printf("\b+-");
                /* correct last child */
-               if(last_child) {
+               if (last_child) {
                        pre[index-1]=' ';
                }
        } /* if not root hub */
@@ -284,29 +284,29 @@ void usb_show_tree_graph(struct usb_device *dev,char *pre)
        pre[index]=0;
        printf(" %s (%s, %dmA)\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
                dev->slow ? "1.5MBit/s" : "12MBit/s",dev->config.MaxPower * 2);
-       if(strlen(dev->mf) ||
+       if (strlen(dev->mf) ||
           strlen(dev->prod) ||
           strlen(dev->serial))
                printf(" %s  %s %s %s\n",pre,dev->mf,dev->prod,dev->serial);
        printf(" %s\n",pre);
-       if(dev->maxchild>0) {
+       if (dev->maxchild>0) {
                for(i=0;i<dev->maxchild;i++) {
-                       if(dev->children[i]!=NULL) {
+                       if (dev->children[i]!=NULL) {
                                usb_show_tree_graph(dev->children[i],pre);
                                pre[index]=0;
                        }
                }
        }
-}      
+}
 
 /* main routine for the tree command */
 void usb_show_tree(struct usb_device *dev)
 {
        char preamble[32];
-       
+
        memset(preamble,0,32);
        usb_show_tree_graph(dev,&preamble[0]);
-}      
+}
 
 
 
@@ -355,7 +355,7 @@ int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                printf ("\n** Device %d not available\n", dev);
                return 1;
        }
-       if(stor_dev->block_read==NULL) {
+       if (stor_dev->block_read==NULL) {
                printf("storage device not initialized. Use usb scan\n");
                return 1;
        }
@@ -366,7 +366,7 @@ int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
                part = simple_strtoul(++ep, NULL, 16);
        }
-       
+
        if (get_partition_info (stor_dev, part, &info)) {
                /* try to boot raw .... */
                strncpy(&info.type[0], BOOT_PART_TYPE, sizeof(BOOT_PART_TYPE));
@@ -414,6 +414,9 @@ int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        }
        /* Loading ok, update default load address */
        load_addr = addr;
+
+       flush_cache (addr, (cnt+1)*info.blksz);
+
        /* Check if we should attempt an auto-start */
        if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
                char *local_args[2];
@@ -430,13 +433,12 @@ int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 
 
 
-
 /*********************************************************************************
  * usb command intepreter
  */
 int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 {
-       
+
        int i;
        struct usb_device *dev;
        block_dev_desc_t *stor_dev;
@@ -446,12 +448,12 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                usb_stop();
                printf("(Re)start USB...\n");
                usb_init();
-               return 0; 
-       } 
+               return 0;
+       }
        if (strncmp(argv[1],"stop",4) == 0) {
-#ifdef CONFIG_USB_KEYBOARD 
-               if(argc==2) {
-                       if(usb_kbd_deregister()!=0) {
+#ifdef CONFIG_USB_KEYBOARD
+               if (argc==2) {
+                       if (usb_kbd_deregister()!=0) {
                                printf("USB not stopped: usbkbd still using USB\n");
                                return 1;
                        }
@@ -464,18 +466,18 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                printf("stopping USB..\n");
                usb_stop();
                return 0;
-       } 
+       }
        if (strncmp(argv[1],"tree",4) == 0) {
                printf("\nDevice Tree:\n");
-               usb_show_tree(usb_get_dev_index(0));    
+               usb_show_tree(usb_get_dev_index(0));
                return 0;
        }
        if (strncmp(argv[1],"inf",3) == 0) {
                int d;
-               if(argc==2) {
+               if (argc==2) {
                        for(d=0;d<USB_MAX_DEVICE;d++) {
                                dev=usb_get_dev_index(d);
-                               if(dev==NULL) 
+                               if (dev==NULL)
                                        break;
                                usb_display_desc(dev);
                                usb_display_config(dev);
@@ -484,17 +486,17 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
                else {
                        int d;
-                       
+
                        i=simple_strtoul(argv[2], NULL, 16);
                        printf("config for device %d\n",i);
                        for(d=0;d<USB_MAX_DEVICE;d++) {
                                dev=usb_get_dev_index(d);
-                               if(dev==NULL) 
+                               if (dev==NULL)
                                        break;
-                               if(dev->devnum==i)
+                               if (dev->devnum==i)
                                        break;
                        }
-                       if(dev==NULL) {
+                       if (dev==NULL) {
                                printf("*** NO Device avaiable ***\n");
                                return 0;
                        }
@@ -509,12 +511,12 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        if (strncmp(argv[1],"scan",4) == 0) {
                printf("Scan for storage device:\n");
                usb_stor_curr_dev=usb_stor_scan(1);
-               if(usb_stor_curr_dev==-1) {
+               if (usb_stor_curr_dev==-1) {
                        printf("No device found. Not initialized?\n");
                        return 1;
                }
                return 0;
-       } 
+       }
        if (strncmp(argv[1],"part",4) == 0) {
                int devno, ok;
                for (ok=0, devno=0; devno<USB_MAX_STOR_DEV; ++devno) {
@@ -534,11 +536,11 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                return 0;
        }
        if (strcmp(argv[1],"read") == 0) {
-               if(usb_stor_curr_dev<0) {
+               if (usb_stor_curr_dev<0) {
                        printf("no current device selected\n");
                        return 1;
                }
-               if(argc==5) {
+               if (argc==5) {
                        unsigned long addr = simple_strtoul(argv[2], NULL, 16);
                        unsigned long blk  = simple_strtoul(argv[3], NULL, 16);
                        unsigned long cnt  = simple_strtoul(argv[4], NULL, 16);
@@ -548,13 +550,13 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        stor_dev=usb_stor_get_dev(usb_stor_curr_dev);
                        n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt, (ulong *)addr);
                        printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
-                       if(n==cnt)
+                       if (n==cnt)
                                return 0;
                        return 1;
                }
        }
        if (strcmp(argv[1],"dev") == 0) {
-               if(argc==3) {
+               if (argc==3) {
                        int dev = (int)simple_strtoul(argv[2], NULL, 10);
                        printf ("\nUSB device %d: ", dev);
                        if (dev >= USB_MAX_STOR_DEV) {
@@ -564,7 +566,7 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        printf ("\n    Device %d: ", dev);
                        stor_dev=usb_stor_get_dev(dev);
                        dev_print(stor_dev);
-                       if(stor_dev->type == DEV_TYPE_UNKNOWN) {
+                       if (stor_dev->type == DEV_TYPE_UNKNOWN) {
                                return 1;
                        }
                        usb_stor_curr_dev = dev;
@@ -575,7 +577,7 @@ int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        printf ("\nUSB device %d: ", usb_stor_curr_dev);
                        stor_dev=usb_stor_get_dev(usb_stor_curr_dev);
                        dev_print(stor_dev);
-                       if(stor_dev->type == DEV_TYPE_UNKNOWN) {
+                       if (stor_dev->type == DEV_TYPE_UNKNOWN) {
                                return 1;
                        }
                        return 0;
index e296ee8ac5fecf162585df1579acb7d43b7552ca..3eb07c6b3b27df8a02d05056610fd1924b36b832 100644 (file)
@@ -460,6 +460,9 @@ int disable_interrupts (void);
 ulong  lcd_setmem (ulong);
 #endif /* CONFIG_LCD */
 
+/* ppc/cache.c */
+void   flush_cache   (unsigned long, unsigned long);
+
 /* ppc/ticks.S */
 unsigned long long get_ticks(void);
 void   wait_ticks    (unsigned long);
index 2de7de8dff1a1c16e42bef76cf6bbb43f7e06842..15202c8a1acfcd432a7d02d0ce70f10961b1a03d 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -247,7 +247,7 @@ restart:
                                setenv("filesize", buf);
                        }
                        eth_halt();
-                       return 1;
+                       return NetBootFileXferSize;
 
                case NETLOOP_FAIL:
                        return 0;
index 0235dd28e8d1d91a542c9901a591f92a48813982..537fa15b1079f680f753ceb85bed63d22826eff3 100644 (file)
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
 LIB    = lib$(ARCH).a
 
 AOBJS  = ppcstring.o ticks.o
-COBJS  = ctype.o vsprintf.o extable.o string.o time.o \
+COBJS  = cache.o ctype.o vsprintf.o extable.o string.o time.o \
          display_options.o zlib.o crc32.o kgdb.o ldiv.o
 OBJS   = $(AOBJS) $(COBJS)
 
diff --git a/ppc/cache.c b/ppc/cache.c
new file mode 100644 (file)
index 0000000..a6ae9cc
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+
+void flush_cache (ulong start_addr, ulong size)
+{
+       ulong addr, end_addr = start_addr + size;
+
+       if (CFG_CACHELINE_SIZE) {
+               addr = start_addr & (CFG_CACHELINE_SIZE - 1);
+               for (addr = start_addr;
+                    addr < end_addr;
+                    addr += CFG_CACHELINE_SIZE) {
+                       asm ("dcbst 0,%0": :"r" (addr));
+               }
+               asm ("sync");   /* Wait for all dcbst to complete on bus */
+
+               for (addr = start_addr;
+                    addr < end_addr;
+                    addr += CFG_CACHELINE_SIZE) {
+                       asm ("icbi 0,%0": :"r" (addr));
+               }
+       }
+       asm ("sync");           /* Always flush prefetch queue in any case */
+       asm ("isync");
+}