dumper.c

00001 /* dumper.c -- Dump content of memory.
00002    Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
00003    Written by Stephane Carrez (stcarrez@nerim.fr)
00004 
00005 This file is part of GTAM.
00006 
00007 GTAM is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 GTAM is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GTAM; see the file COPYING.  If not, write to
00019 the Free Software Foundation, 59 Temple Place - Suite 330,
00020 Boston, MA 02111-1307, USA.  */
00021 
00074 #include <sys/ports.h>
00075 
00076 int __attribute__((noreturn)) main (void);
00077 static unsigned short get_char (void);
00078 void _start (void);
00079 
00080 void
00081 _start ()
00082 {
00083   set_bus_expanded ();
00084 
00085   main ();
00086 }
00087 
00088 /* Write a character on the serial line.  */
00089 static void
00090 put_char (unsigned char c)
00091 {
00092   while (!(_io_ports[M6811_SCSR] & M6811_TDRE))
00093     continue;
00094 
00095   _io_ports[M6811_SCDR] = c;
00096   _io_ports[M6811_SCCR2] |= M6811_TE;
00097 }
00098 
00099 /* Write an escaped byte on the serial line.  */
00100 static void
00101 put_byte (unsigned char c)
00102 {
00103   /* Don't send \n and escape directly as they may confuse some
00104      synchronisation.  */
00105   if (c == '\n' || c == '\033')
00106     {
00107       put_char ('\033');
00108       c ^= 0x20;
00109     }
00110   put_char (c);
00111 }
00112 
00113 static inline void
00114 reboot()
00115 {
00116 #ifndef NO_REBOOT
00117   /* The 'func' type is marked as 'noreturn' to optimize the
00118      generated code.  */
00119   typedef void __attribute__ ((noreturn)) (* func)();
00120 
00121   func handler;
00122 
00123   set_bus_single_chip ();
00124 
00125   /* To reboot, get the reset vector and go to the start of the ROM.  */
00126   handler = *((func*) 0xbffe);
00127   handler ();
00128 #endif
00129 }
00130 
00131 int
00132 main ()
00133 {
00134   unsigned char* addr;
00135   unsigned char c;
00136   
00137   while (1)
00138     {
00139       /* Print banner for synchronization.  */
00140       put_char ('\n');
00141       put_char ('>');
00142 
00143       /* Wait for command.  */
00144       c = get_char ();
00145 
00146       /* Read memory command.  Command format is:
00147 
00148          R<ADDR-HIGH><ADDR-LOW><SIZE>
00149 
00150          Address and size are passed in binary form.
00151          A size of 0 corresponds to 256 bytes.
00152 
00153          We reply with:
00154 
00155          <SIZE><DATA><CRC>
00156 
00157          where size, data and crc are returned in binary form.  */
00158       if (c == 'R')
00159         {
00160           unsigned char size;
00161           unsigned char crc;
00162           
00163           c = get_char ();
00164           addr = (unsigned char*) ((c << 8) | get_char ());
00165           size = get_char ();
00166 
00167           /* Give a feedback about what we are going to send.  */
00168           put_byte (size);
00169 
00170           crc = 0;
00171           do
00172             {
00173               c = *addr++;
00174               crc ^= c;
00175               put_byte (c);
00176             }
00177           while (--size != 0);
00178           put_byte (crc);
00179         }
00180 
00181       /* Reboot command.  Command format is:
00182 
00183          Z
00184 
00185          We reply with a Z.  The final \n is not seen because it is
00186          clobbered during the reboot.  */
00187       else if (c == 'Z')
00188         {
00189           put_char (c);
00190           put_char ('\n');
00191 
00192           reboot ();
00193         }
00194 
00195       /* For others, emit something to tell we are alive.  */
00196       else
00197         {
00198           put_char ('?');
00199         }
00200     }
00201 }
00202 
00203 #ifndef NO_BREAK
00204 static inline void
00205 restart ()
00206 {
00207   unsigned short i;
00208   volatile unsigned char* ports = &_io_ports[0];
00209 
00210   /* Wait for the transmitter to be ready.  */
00211   while (!(ports[M6811_SCSR] & M6811_TDRE))
00212     continue;
00213   
00214   /* Send a break.  */
00215   ports[M6811_SCCR2] |= M6811_SBK;
00216 
00217   /* Wait some time (??? is it necessary ???).  */
00218   for (i = 1000; --i != 0;)
00219     (void) ports[M6811_TCTN];
00220 
00221   ports[M6811_SCCR2] &= ~M6811_SBK;
00222 
00223   /* Go back to the main with some longjump.  We can't go to _start()
00224      because it was clobbered by the ZTMP and ZREG registers.  */
00225   __asm__ __volatile__ ("lds #0x0ff");
00226   __asm__ __volatile__ ("bra main");
00227 }
00228 #endif
00229 
00230 static unsigned short
00231 get_char ()
00232 {
00233   unsigned char c;
00234   volatile unsigned char* ports = &_io_ports[0];
00235   
00236   while (1)
00237     {
00238       c = ports[M6811_SCSR];
00239 
00240 #ifndef NO_BREAK
00241       /* If there is a read error or a break, abort everything and
00242          restart.  When restarting we send a break so that the host
00243          knows we are restarting.  */
00244       if (c & M6811_FE)
00245         restart ();
00246 #endif
00247 
00248       if (c & M6811_RDRF)
00249         break;
00250     }
00251   return ports[M6811_SCDR];
00252 }