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_TCNT]; 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 }