Logo Search packages:      
Sourcecode: m68k-vme-tftplilo version File versions  Download package

mvme.c

/*
 *  VME Linux/m68k TFTP Loader
 *
 *  (c) Copyright 1998 by Nick Holgate
 *
 *  This file is subject to the terms and conditions of the GNU General
 *  Public License.  See the file COPYING for more details.
 */

/*--------------------------------------------------------------------------*/

#include "defs.h"
#include "mvmebug.h"

/*--------------------------------------------------------------------------*/

static BRDID_PKT  *brdid_ptr;
static NETBOOTINFO      *netbootinfo;
static char             bootargs[65];

/*--------------------------------------------------------------------------*/

void
loader_init
(     CALLREGS    *regs
)
{     char        *s;
      char        *d;

      /* save pointer to netboot info */
      netbootinfo = (NETBOOTINFO *) regs->a[2];

      /* copy argument string */
      s = regs->a[3];
      d = bootargs;
      while (s != regs->a[4])
            *d++ = *s++;
      *d = '\0';

      put_str("\nMotorola MVME TFTP Linux Loader V" VERSION "\n\n");

      /* identify board */
      brdid_ptr = MVMEBug_brdid();

      if ((brdid_ptr->bdid != 0x42444944)
      &&    (brdid_ptr->bdid != 0x21494421))
      {
            panic("Cannot identify board");
      }
}

/*--------------------------------------------------------------------------*/
/* Print character.
 */

void
put_char
(     const int   c
)
{
      if (c == '\n')
            MVMEBug_putchar('\r');

      MVMEBug_putchar(c);
}

/*--------------------------------------------------------------------------*/

unsigned long
get_time
(     void
)
{     unsigned char buf[8];

      MVMEBug_rtc_read(buf);
      return      (BCD2BIN(buf[4]) * 24)
            +     (BCD2BIN(buf[5]) * 60)
            +    BCD2BIN(buf[6]);
}

/*--------------------------------------------------------------------------*/
/* Wait for and return character from keyboard.
 */

int
get_char
(     unsigned long     timeout           /* maximum time to wait for character           */
)
{     unsigned long     start;
      unsigned long     now;

      if (timeout)
      {
            /* get start time */
            start = get_time();

            /* get timeout second */
            timeout += start;

            while (MVMEBug_getchar_status() == 0)
            {
                  /* check for wrap at midnight */
                  if ((now = get_time()) < start)
                  {
                        /* adjust */
                        now += (60 * 60 * 24);
                  }

                  /* check for timeout */
                  if (now > timeout)
                  {
                        /* timeout */
                        break;
                  }
            }

            if (MVMEBug_getchar_status() == 0)
                  return -1;
      }

      return MVMEBug_getchar();
}

/*--------------------------------------------------------------------------*/
/* return pointer to string containing specified IP address or NULL
 * if not available.
 */

const char *
get_ip
(     IPTYPE                  type
)
{     unsigned long     ip;

      switch (type)
      {
            case IP_CLIENT   : ip = netbootinfo->cipa;       break;
            case IP_SERVER   : ip = netbootinfo->sipa;       break;
            case IP_GATEWAY  : ip = netbootinfo->gipa;       break;
            case IP_BROADCAST: ip = netbootinfo->broadcast;  break;
            case IP_NETMASK  : ip = netbootinfo->subnetmask; break;
            default          : return NULL;
      }
            
      return mkinet(ip);
}

/*--------------------------------------------------------------------------*/
/* return pointer to prototype configuration file name
 */

const char *
config_filename
(     void
)
{
      /* use boot argument string if set */
      if (bootargs[0])
            return bootargs;

      /* use compiled in default */
      return DEFAULT_CONFIG_FILE_NAME;
}

/*--------------------------------------------------------------------------*/

int
tftp_read
(     const char        *filename,
      unsigned long     count,
      void              *buffer
)
{     NIOPCALL          niop;

      niop.clun    = 0;
      niop.dlun    = 0;
      niop.status  = 0;
      niop.address = (unsigned long) buffer;
      niop.length  = count;
      niop.offset  = 0;
      niop.time    = 0;
      niop.bytes   = 0;
      strncpy(niop.filename, filename, sizeof(niop.filename) - 1);
      niop.filename[sizeof(niop.filename) - 1] = '\0';

      MVMEBug_net_read(&niop);

      if (niop.status)
      {
            printf("TFTP READ FAILED: status=%04x\n", niop.status);
            return FAILURE;
      }

      return niop.bytes;
}

/*--------------------------------------------------------------------------*/

unsigned long
get_compat_booti_version
(     void
)
{
      switch (brdid_ptr->brdno)
      {
            case 0x0162:
            case 0x0172: return COMPAT_MVME162_BOOTI_VERSION;
            default    : return COMPAT_MVME167_BOOTI_VERSION;
      }
}

/*--------------------------------------------------------------------------*/

unsigned long
get_booti_version
(     void
)
{
      return MVME16x_BOOTI_VERSION;
}

/*--------------------------------------------------------------------------*/

unsigned long
get_compat_machtype
(     void
)
{
      switch (brdid_ptr->brdno)
      {
            case 0x0162:
            case 0x0172: return COMPAT_MACH_MVME162;
            default    : return COMPAT_MACH_MVME167;
      }
}

/*--------------------------------------------------------------------------*/

unsigned long
get_machtype
(     void
)
{
      return MACH_MVME16x;
}

/*--------------------------------------------------------------------------*/
/*
 *    This assembler code is copied into the base of the stack, and then executed.
 *    It copies the kernel and ramdisk images to their final resting places.
 *
 *    It is called with:
 *
 *      a0 = address of this code (very top of memory)
 *      a1 = kernel destination address (low memory 0x1000)
 *          a2 = kernel source address
 *          a3 = ramdisk destination address (just below this code)
 *          a4 = ramdisk source address
 *          d0 = kernel size + size of bootinfo data rounded up next multiple of 4
 *          d1 = ramdisk size rounded to next multiple of 1K
 *      d2 = non-zero if 16x-Bug should be called
 */

__asm(".text\n"
__ALIGN_STR "\n"
".globl " SYMBOL_NAME_STR(startcode_beg) ";\n"
".globl " SYMBOL_NAME_STR(startcode_end) ";\n"
SYMBOL_NAME_STR(startcode_beg) ":                                                                     \n\
                                                | copy the ramdisk to the top of memory               \n\
                                                | (from back to front)                                      \n\
            addl  %d1,%a4                 | src   = (u_long *) (rd_src + rd_size);        \n\
            movel %a3,%a5                                                                                         \n\
            addl  %d1,%a5                 | dest  = (u_long *) (rd_dest + rd_size);       \n\
                                                                                                                        \n\
            bras  2f                      | do                                                              \n\
1:          movel -(%a4),-(%a5)     |   *--dest = *--src;                                       \n\
2:          cmpl  %a3,%a5                 | while (dest > ramdisk_dest)                         \n\
            jgt         1b                      |                                                                       \n\
                                                                                                                        \n\
                                                | copy kernel text and data, and bootinfo       \n\
            movel %a2,%a4                 | limit = (u_long *) (kernel_src + kernel_size);\n\
            addl  %d0,%a4                                                                                         \n\
            movel %a1,%a5                 | dest  = (u_long *) kernel_dest                      \n\
                                                                                                                        \n\
            bras  2f                      | do                                                              \n\
1:          movel (%a2)+,(%a5)+     |  *dest++ = *src++;                                        \n\
2:          cmpl  %a4,%a2                 | while (src < limit)                                       \n\
            jlt         1b                      |                                                                       \n\
                                                                                                                        \n\
            dc.w  0xf498                  | cinva     ic | invalidate instruction cache         \n\
                                                                                                                        \n\
            tstl  %d2                     | call monitor?                                                   \n\
            jeq         1f                      | branch if not                                                   \n\
                                                                                                                        \n\
            trap  #15                     | return to 16x-Bug                                               \n\
            dc.w  0x0063                                                                                          \n\
                                                                                                                        \n\
1:          jmp         (%a1)             | start kernel                                                    \n\
"
SYMBOL_NAME_STR(startcode_end) ":                                                                     \n\
");

/*--------------------------------------------------------------------------*/

void
print_model
(     void
)
{     char  suf[4];

      suf[1] = brdid_ptr->suffix[0];
      suf[2] = brdid_ptr->suffix[1];
      suf[3] = '\0';
      suf[0] = suf[1] ? '-' : '\0';

      printf("MVME%x%s", brdid_ptr->brdno, suf);
}

/*--------------------------------------------------------------------------*/

unsigned long
get_vme_type
(     void
)
{
      switch (brdid_ptr->brdno)
      {
            case 0x0162: return VME_TYPE_MVME162;
            case 0x0166: return VME_TYPE_MVME166;
            case 0x0167: return VME_TYPE_MVME167;
            case 0x0172: return VME_TYPE_MVME172;
            case 0x0177: return VME_TYPE_MVME177;
            default    : return -1; 
      }
}

/*--------------------------------------------------------------------------*/

int
add_vme_bootinfo
(     void
)
{     unsigned long     vme_type = get_vme_type();


      if (vme_type != -1)
      {
            if (!add_bi_record(BI_VME_TYPE, sizeof(vme_type), &vme_type))
                  return FALSE;
      }

      if (!add_bi_record(BI_VME_BRDINF, sizeof(BRDID_PKT), brdid_ptr))
            return FALSE;

      return TRUE;
}

/*-----------------------------< end of file >------------------------------*/

Generated by  Doxygen 1.6.0   Back to index