コード例 #1
0
ファイル: bspstart.c プロジェクト: epicsdeb/rtems
void bsp_start( void )
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
#if !defined(mvme2100)
  unsigned l2cr;
#endif
  uintptr_t intrStackStart;
  uintptr_t intrStackSize;
  ppc_cpu_id_t myCpu;
  ppc_cpu_revision_t myCpuRevision;
  prep_t boardManufacturer;
  motorolaBoard myBoard;
  Triv121PgTbl	pt=0;

  /*
   * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
   * function store the result in global variables so that it can be used
   * later...
   */
  myCpu 	= get_ppc_cpu_type();
  myCpuRevision = get_ppc_cpu_revision();

  /*
   * Init MMU block address translation to enable hardware access
   */

#if !defined(mvme2100)
  /*
   * PC legacy IO space used for inb/outb and all PC compatible hardware
   */
  setdbat(1, _IO_BASE, _IO_BASE, 0x10000000, IO_PAGE);
#endif

  /*
   * PCI devices memory area. Needed to access OpenPIC features
   * provided by the Raven
   *
   * T. Straumann: give more PCI address space
   */
  setdbat(2, PCI_MEM_BASE+PCI_MEM_WIN0, PCI_MEM_BASE+PCI_MEM_WIN0, 0x10000000, IO_PAGE);

  /*
   * Must have acces to open pic PCI ACK registers provided by the RAVEN
   */
  setdbat(3, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);

#if defined(mvme2100)
  /* Need 0xfec00000 mapped for this */
  EUMBBAR = get_eumbbar();
#endif

  /*
   * enables L1 Cache. Note that the L1_caches_enables() codes checks for
   * relevant CPU type so that the reason why there is no use of myCpu...
   */
  L1_caches_enables();

#if !defined(mvme2100)
  /*
   * Enable L2 Cache. Note that the set_L2CR(L2CR) codes checks for
   * relevant CPU type (mpc750)...
   */
  l2cr = get_L2CR();
#ifdef SHOW_LCR2_REGISTER
  printk("Initial L2CR value = %x\n", l2cr);
#endif
  if ( (! (l2cr & 0x80000000)) && ((int) l2cr == -1))
    set_L2CR(0xb9A14000);
#endif

  /*
   * Initialize the interrupt related settings.
   */
  intrStackStart = (uintptr_t) __rtems_end;
  intrStackSize = rtems_configuration_get_interrupt_stack_size();

  /*
   * Initialize default raw exception handlers.
   */
  sc = ppc_exc_initialize(
    PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
    intrStackStart,
    intrStackSize
  );
  if (sc != RTEMS_SUCCESSFUL) {
    BSP_panic("cannot initialize exceptions");
  }

  select_console(CONSOLE_LOG);

  /*
   * We check that the keyboard is present and immediately
   * select the serial console if not.
   */
#if defined(BSP_KBD_IOBASE)
  { int err;
    err = kbdreset();
    if (err) select_console(CONSOLE_SERIAL);
  }
#else
  select_console(CONSOLE_SERIAL);
#endif

  boardManufacturer   =  checkPrepBoardType(&residualCopy);
  if (boardManufacturer != PREP_Motorola) {
    printk("Unsupported hardware vendor\n");
    while (1);
  }
  myBoard = getMotorolaBoard();

  printk("-----------------------------------------\n");
  printk("Welcome to %s on %s\n", _RTEMS_version,
                                    motorolaBoardToString(myBoard));
  printk("-----------------------------------------\n");
#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Residuals are located at %x\n", (unsigned) &residualCopy);
  printk("Additionnal boot options are %s\n", loaderParam);
  printk("Initial system stack at %x\n",stack);
  printk("Software IRQ stack starts at %x with size %u\n", intrStackStart, intrStackSize);
  printk("-----------------------------------------\n");
#endif

#ifdef TEST_RETURN_TO_PPCBUG
  printk("Hit <Enter> to return to PPCBUG monitor\n");
  printk("When Finished hit GO. It should print <Back from monitor>\n");
  debug_getc();
  _return_to_ppcbug();
  printk("Back from monitor\n");
  _return_to_ppcbug();
#endif /* TEST_RETURN_TO_PPCBUG  */

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Going to start PCI buses scanning and initialization\n");
#endif

  pci_initialize();
  {
    const struct _int_map *bspmap  = motorolaIntMap(currentBoard);
    if( bspmap ) {
       printk("pci : Configuring interrupt routing for '%s'\n",
          motorolaBoardToString(currentBoard));
       FixupPCI(bspmap, motorolaIntSwizzle(currentBoard));
    }
    else
       printk("pci : Interrupt routing not available for this bsp\n");
 }

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Number of PCI buses found is : %d\n", pci_bus_count());
#endif
#ifdef TEST_RAW_EXCEPTION_CODE
  printk("Testing exception handling Part 1\n");
  /*
   * Cause a software exception
   */
  __asm__ __volatile ("sc");
  /*
   * Check we can still catch exceptions and return coorectly.
   */
  printk("Testing exception handling Part 2\n");
  __asm__ __volatile ("sc");

  /*
   * Somehow doing the above seems to clobber SPRG0 on the mvme2100.  The
   * interrupt disable mask is stored in SPRG0. Is this a problem?
   */
  ppc_interrupt_set_disable_mask( PPC_INTERRUPT_DISABLE_MASK_DEFAULT);

#endif

/* See above */

  BSP_mem_size            = residualCopy.TotalMemory;
  BSP_bus_frequency       = residualCopy.VitalProductData.ProcessorBusHz;
  BSP_processor_frequency = residualCopy.VitalProductData.ProcessorHz;
  BSP_time_base_divisor   = (residualCopy.VitalProductData.TimeBaseDivisor?
                    residualCopy.VitalProductData.TimeBaseDivisor : 4000);

  /* clear hostbridge errors but leave MCP disabled -
   * PCI config space scanning code will trip otherwise :-(
   */
  _BSP_clear_hostbridge_errors(0 /* enableMCP */, 0/*quiet*/);

  /* Allocate and set up the page table mappings
   * This is only available on >604 CPUs.
   *
   * NOTE: This setup routine may modify the available memory
   *       size. It is essential to call it before
   *       calculating the workspace etc.
   */
  pt = BSP_pgtbl_setup(&BSP_mem_size);

  if (!pt || TRIV121_MAP_SUCCESS != triv121PgTblMap(
            pt, TRIV121_121_VSID, 0xfeff0000, 1,
            TRIV121_ATTR_IO_PAGE, TRIV121_PP_RW_PAGE)) {
	printk("WARNING: unable to setup page tables VME "
               "bridge must share PCI space\n");
  }

  /*
   *  initialize the device driver parameters
   */
  bsp_clicks_per_usec 	 = BSP_bus_frequency/(BSP_time_base_divisor * 1000);

  /*
   * Initalize RTEMS IRQ system
   */
  BSP_rtems_irq_mng_init(0);

  /* Activate the page table mappings only after
   * initializing interrupts because the irq_mng_init()
   * routine needs to modify the text
   */
  if (pt) {
#ifdef  SHOW_MORE_INIT_SETTINGS
    printk("Page table setup finished; will activate it NOW...\n");
#endif
    BSP_pgtbl_activate(pt);
    /* finally, switch off DBAT3 */
    setdbat(3, 0, 0, 0, 0);
  }

#if defined(DEBUG_BATS)
  ShowBATS();
#endif

#ifdef SHOW_MORE_INIT_SETTINGS
  printk("Exit from bspstart\n");
#endif
}
コード例 #2
0
ファイル: bootcard.c プロジェクト: phipse/L4RTEMS
/*
 *  This is the initialization framework routine that weaves together
 *  calls to RTEMS and the BSP in the proper sequence to initialize
 *  the system while maximizing shared code and keeping BSP code in C
 *  as much as possible.
 */
int boot_card(
    const char *cmdline
)
{
    rtems_interrupt_level  bsp_isr_level;
    void                  *work_area_start = NULL;
    uintptr_t              work_area_size = 0;
    void                  *heap_start = NULL;
    uintptr_t              heap_size = 0;

    /*
     * Special case for PowerPC: The interrupt disable mask is stored in SPRG0.
     * It must be valid before we can use rtems_interrupt_disable().
     */
#ifdef PPC_INTERRUPT_DISABLE_MASK_DEFAULT
    ppc_interrupt_set_disable_mask( PPC_INTERRUPT_DISABLE_MASK_DEFAULT );
#endif /* PPC_INTERRUPT_DISABLE_MASK_DEFAULT */

    /*
     *  Make sure interrupts are disabled.
     */
    rtems_interrupt_disable( bsp_isr_level );

    bsp_boot_cmdline = cmdline;

    /*
     * Invoke Board Support Package initialization routine written in C.
     */
    bsp_start();

    /*
     *  Find out where the block of memory the BSP will use for
     *  the RTEMS Workspace and the C Program Heap is.
     */
    bsp_get_work_area(&work_area_start, &work_area_size,
                      &heap_start, &heap_size);

    if ( work_area_size <= Configuration.work_space_size ) {
        printk(
            "bootcard: work space too big for work area: %p > %p\n",
            (void *) Configuration.work_space_size,
            (void *) work_area_size
        );
        bsp_cleanup();
        return -1;
    }

    if ( rtems_unified_work_area ) {
        Configuration.work_space_start = work_area_start;
        Configuration.work_space_size  = work_area_size;
    } else {
        Configuration.work_space_start = work_area_start;
    }

#if (BSP_DIRTY_MEMORY == 1)
    memset( work_area_start, 0xCF,  work_area_size );
#endif

    /*
     *  Initialize RTEMS data structures
     */
    rtems_initialize_data_structures();

    /*
     *  Initialize the C library for those BSPs using the shared
     *  framework.
     */
    bootcard_bsp_libc_helper(
        work_area_start,
        work_area_size,
        heap_start,
        heap_size
    );

    /*
     *  All BSP to do any required initialization now that RTEMS
     *  data structures are initialized.  In older BSPs or those
     *  which do not use the shared framework, this is the typical
     *  time when the C Library is initialized so malloc()
     *  can be called by device drivers.  For BSPs using the shared
     *  framework, this routine can be empty.
     */
    bsp_pretasking_hook();

    /*
     *  If debug is enabled, then enable all dynamic RTEMS debug
     *  capabilities.
     *
     *  NOTE: Most debug features are conditionally compiled in
     *        or enabled via configure time plugins.
     */
#ifdef RTEMS_DEBUG
    rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
#endif

    /*
     *  Let RTEMS perform initialization it requires before drivers
     *  are allowed to be initialized.
     */
    rtems_initialize_before_drivers();

    /*
     *  Execute BSP specific pre-driver hook. Drivers haven't gotten
     *  to initialize yet so this is a good chance to initialize
     *  buses, spurious interrupt handlers, etc..
     *
     *  NOTE: Many BSPs do not require this handler and use the
     *        shared stub.
     */
    bsp_predriver_hook();

    /*
     *  Initialize all device drivers.
     */
    rtems_initialize_device_drivers();

    /*
     *  Invoke the postdriver hook.  This normally opens /dev/console
     *  for use as stdin, stdout, and stderr.
     */
    bsp_postdriver_hook();

    /*
     *  Complete initialization of RTEMS and switch to the first task.
     *  Global C++ constructors will be executed in the context of that task.
     */
    rtems_initialize_start_multitasking();

    /***************************************************************
     ***************************************************************
     *  APPLICATION RUNS HERE!!!  When it shuts down, we return!!! *
     ***************************************************************
     ***************************************************************
     */

    /*
     *  Perform any BSP specific shutdown actions which are written in C.
     */
    bsp_cleanup();

    /*
     *  Now return to the start code.
     */
    return 0;
}
コード例 #3
0
rtems_status_code ppc_exc_initialize(
  uint32_t interrupt_disable_mask,
  uintptr_t interrupt_stack_begin,
  uintptr_t interrupt_stack_size
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  const ppc_exc_categories *const categories = ppc_exc_current_categories();
  uintptr_t const interrupt_stack_end = interrupt_stack_begin + interrupt_stack_size;
  uintptr_t interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
  unsigned vector = 0;
  uint32_t sda_base = 0;
  uint32_t r13 = 0;

  if (categories == NULL) {
    return RTEMS_NOT_IMPLEMENTED;
  }

  /* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure
   * early init code put it there.
   */
  __asm__ volatile (
    "lis %0, _SDA_BASE_@h\n"
    "ori %0, %0, _SDA_BASE_@l\n"
    "mr  %1, 13\n"
    : "=r" (sda_base), "=r"(r13)
  );

  if (sda_base != r13) {
    return RTEMS_NOT_CONFIGURED;
  }

  /* Ensure proper interrupt stack alignment */
  interrupt_stack_pointer &= ~((uintptr_t) CPU_STACK_ALIGNMENT - 1);

  /* Tag interrupt stack bottom */
  *(uint32_t *) interrupt_stack_pointer = 0;

  /* Move interrupt stack values to special purpose registers */
  PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG1, interrupt_stack_pointer);
  PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG2, interrupt_stack_begin);

  ppc_interrupt_set_disable_mask(interrupt_disable_mask);

  /* Use current MMU / RI settings when running C exception handlers */
  ppc_exc_msr_bits = ppc_machine_state_register() & (MSR_DR | MSR_IR | MSR_RI);

#ifdef __ALTIVEC__
  /* Need vector unit enabled to save/restore altivec context */
  ppc_exc_msr_bits |= MSR_VE;
#endif
 
  if (ppc_cpu_is_bookE() == PPC_BOOKE_STD || ppc_cpu_is_bookE() == PPC_BOOKE_E500) {
    ppc_exc_initialize_booke();
  }

  for (vector = 0; vector <= LAST_VALID_EXC; ++vector) {
    ppc_exc_category category = ppc_exc_category_for_vector(categories, vector);

    if (category != PPC_EXC_INVALID) {
      void *const vector_address = ppc_exc_vector_address(vector);
      uint32_t prologue [16];
      size_t prologue_size = sizeof(prologue);

      sc = ppc_exc_make_prologue(vector, category, prologue, &prologue_size);
      if (sc != RTEMS_SUCCESSFUL) {
        return RTEMS_INTERNAL_ERROR;
      }

      ppc_code_copy(vector_address, prologue, prologue_size);
    }
  }

  /* If we are on a classic PPC with MSR_DR enabled then
   * assert that the mapping for at least this task's
   * stack is write-back-caching enabled (see README/CAVEATS)
   * Do this only if the cache is physically enabled.
   * Since it is not easy to figure that out in a
   * generic way we need help from the BSP: BSPs
   * which run entirely w/o the cache may set
   * ppc_exc_cache_wb_check to zero prior to calling
   * this routine.
   *
   * We run this check only after exception handling is
   * initialized so that we have some chance to get
   * information printed if it fails.
   *
   * Note that it is unsafe to ignore this issue; if
   * the check fails, do NOT disable it unless caches
   * are always physically disabled.
   */
  if (ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits)) {
    /* The size of 63 assumes cache lines are at most 32 bytes */
    uint8_t dummy[63];
    uintptr_t p = (uintptr_t) dummy;
    /* If the dcbz instruction raises an alignment exception
     * then the stack is mapped as write-thru or caching-disabled.
     * The low-level code is not capable of dealing with this
     * ATM.
     */
    p = (p + 31U) & ~31U;
    __asm__ volatile ("dcbz 0, %0"::"b" (p));
    /* If we make it thru here then things seem to be OK */
  }