checker.c

00001 /* checker.c -- Check the memory and return the target board memory layout
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 
00091 #include <sys/ports.h>
00092 
00093 static void put_addr(unsigned short value);
00094 static void put_char(unsigned char c);
00095 void _start (void);
00096 
00097 static inline void
00098 reboot()
00099 {
00100 #ifndef NO_REBOOT
00101   /* The 'func' type is marked as 'noreturn' to optimize the
00102      generated code.  */
00103   typedef void __attribute__ ((noreturn)) (* func)();
00104 
00105   func handler;
00106 
00107   set_bus_single_chip ();
00108 
00109   /* To reboot, get the reset vector and go to the start of the ROM.  */
00110   handler = *((func*) 0xbffe);
00111   handler ();
00112 #endif
00113 }
00114 
00115 void
00116 _start()
00117 {
00118   unsigned char c;
00119   volatile unsigned char* addr;
00120   unsigned char nok = 1;
00121 
00122   set_bus_expanded ();
00123 
00124   /* Start at end of the RAM.  The algorithm is basic and destructive.
00125      We can't apply it to the RAM where this program is mapped.  */
00126   addr = (volatile unsigned char*) 0x0ff;
00127   while (1)
00128     {
00129       addr++;
00130 
00131       /* If we reached the end of memory space, flush the SCI by writing
00132          spurious characters and go back to the ROM.  If we don't print
00133          some characters, the BREAK generated by the ROM can eat the
00134          last byte.  */
00135       if (addr == (unsigned char*) 0)
00136         {
00137           for (c = 5; --c != 0; )
00138             put_char ('\n');
00139 
00140           reboot ();
00141 
00142           /* Skip the .page0 if reboot() is not supported.
00143              Otherwise, this code is not reached and not generated.  */
00144           addr += 0xff;
00145           continue;
00146         }
00147 
00148       /* Skip the IO registers.  */
00149       if (addr == _io_ports)
00150         {
00151           addr += M6811_IO_SIZE;
00152           continue;
00153         }
00154 
00155       /* Check the memory by inverting its content.
00156          If this succeeds, we have some kind of RAM.  */
00157       c = ~*addr;
00158       *addr = c;
00159       if (c != *addr)
00160         {
00161           if (nok)
00162             continue;
00163 
00164           /* Beginning of non-RAM bank.  */
00165           nok = 1;
00166           put_char ('-');
00167           put_addr ((unsigned short) addr);
00168         }
00169       else
00170         {
00171           if (nok == 0)
00172              continue;
00173 
00174           /* Beginning of RAM bank.  */
00175           nok = 0;
00176           put_char ('+');
00177           put_addr ((unsigned short) addr);
00178         }
00179     }
00180 }
00181 
00182 
00183 /* Translate and print the 8-bit value in hexadecimal on the serial line.  */
00184 static void
00185 put_hex(unsigned short value)
00186 {
00187   put_char ("0123456789ABCDEF"[(value >> 4) & 0x0F]);
00188   put_char ("0123456789ABCDEF"[value & 0x0F]);
00189 }
00190 
00191 
00192 /* Translate and print the address on the serial line.  */
00193 static void
00194 put_addr(unsigned short value)
00195 {
00196   put_hex (value >> 8);
00197   put_hex (value);
00198   put_char ('\n');
00199 }
00200 
00201 
00202 /* Write a character on the serial line.  */
00203 static void
00204 put_char(unsigned char c)
00205 {
00206   while (!(_io_ports[M6811_SCSR] & M6811_TDRE))
00207     continue;
00208 
00209   _io_ports[M6811_SCDR] = c;
00210   _io_ports[M6811_SCCR2] |= M6811_TE;
00211 }