Home | History | Annotate | Line # | Download | only in common
prom_iface.c revision 1.3
      1  1.1     pooka /* Copyright (c) 1999 The NetBSD Foundation, Inc.
      2  1.1     pooka  * All rights reserved.
      3  1.1     pooka  *
      4  1.1     pooka  * Copyright (c) 2008 Microsoft.  All rights reserved.
      5  1.1     pooka  *
      6  1.1     pooka  * Redistribution and use in source and binary forms, with or without
      7  1.1     pooka  * modification, are permitted provided that the following conditions
      8  1.1     pooka  * are met:
      9  1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     10  1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     11  1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     13  1.1     pooka  *    documentation and/or other materials provided with the distribution.
     14  1.1     pooka  * 3. All advertising materials mentioning features or use of this software
     15  1.1     pooka  *    must display the following acknowledgement:
     16  1.1     pooka  *        This product includes software developed by the NetBSD
     17  1.1     pooka  *        Foundation, Inc. and its contributors.
     18  1.1     pooka  * 4. Neither the name of The NetBSD Foundation nor the names of its
     19  1.1     pooka  *    contributors may be used to endorse or promote products derived
     20  1.1     pooka  *    from this software without specific prior written permission.
     21  1.1     pooka  *
     22  1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23  1.1     pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24  1.1     pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  1.1     pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26  1.1     pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  1.1     pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  1.1     pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     32  1.1     pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33  1.1     pooka  * POSSIBILITY OF SUCH DAMAGE.
     34  1.1     pooka  */
     35  1.1     pooka 
     36  1.1     pooka #include <lib/libsa/stand.h>
     37  1.1     pooka #include <lib/libsa/loadfile.h>
     38  1.1     pooka #include <lib/libkern/libkern.h>
     39  1.1     pooka 
     40  1.1     pooka #include <sys/param.h>
     41  1.1     pooka #include <sys/exec.h>
     42  1.1     pooka #include <sys/exec_elf.h>
     43  1.1     pooka #include <sys/reboot.h>
     44  1.1     pooka 
     45  1.1     pooka #include <machine/emipsreg.h>
     46  1.1     pooka 
     47  1.1     pooka #include "common.h"
     48  1.1     pooka #include "bootinfo.h"
     49  1.1     pooka #include "start.h"
     50  1.1     pooka #include "prom_iface.h"
     51  1.1     pooka 
     52  1.1     pooka #if _DEBUG
     53  1.1     pooka #define TRACE(x) printf x
     54  1.1     pooka #else
     55  1.1     pooka #define TRACE(x)
     56  1.1     pooka #endif
     57  1.1     pooka 
     58  1.1     pooka void epmc_halt(void);
     59  1.1     pooka void save_locore(void);
     60  1.1     pooka void restore_locore(void);
     61  1.2    martin void *nope(void);
     62  1.2    martin void real_halt(void*);
     63  1.2    martin void halt(int *unused, int howto);
     64  1.1     pooka 
     65  1.3  christos static void *nope(void) {return NULL;}
     66  1.1     pooka int getchar(void){return GetChar();}
     67  1.1     pooka 
     68  1.3  christos static void
     69  1.3  christos real_halt(void *arg)
     70  1.1     pooka {
     71  1.1     pooka     int howto = (int)arg;
     72  1.1     pooka     u_int ps = GetPsr();
     73  1.1     pooka 
     74  1.1     pooka     /* Turn off interrupts and the TLB */
     75  1.1     pooka #define EMIPS_SR_RP  0x08000000  /* reduced power */
     76  1.1     pooka #define EMIPS_SR_TS  0x00200000  /* TLB shutdown  */
     77  1.1     pooka #define EMIPS_SR_RST 0x00000080  /* Soft-reset    */
     78  1.1     pooka #define EMIPS_SR_INT 0x0000ff00  /* Interrupt enable mask */
     79  1.1     pooka #define EMIPS_SR_IEc 0x00000001  /* Interrupt enable current */
     80  1.1     pooka 
     81  1.1     pooka     ps &= ~(EMIPS_SR_INT | EMIPS_SR_IEc);
     82  1.1     pooka     ps |= EMIPS_SR_TS;
     83  1.1     pooka     SetPsr(ps);
     84  1.1     pooka 
     85  1.1     pooka     /* Reset entry must be restored for reboot
     86  1.1     pooka      */
     87  1.1     pooka     restore_locore();
     88  1.1     pooka 
     89  1.1     pooka     /* Tell the power manager to halt? */
     90  1.1     pooka     for (;howto & RB_HALT;) {
     91  1.1     pooka         epmc_halt();
     92  1.1     pooka 
     93  1.1     pooka         /* We should not be here!! */
     94  1.1     pooka         ps |= EMIPS_SR_RP | EMIPS_SR_INT; /* but not current */
     95  1.1     pooka         SetPsr(ps);
     96  1.1     pooka     }
     97  1.1     pooka 
     98  1.1     pooka     /* For a reboot, all we can really do is a reset actually */
     99  1.1     pooka     for (;;) {
    100  1.1     pooka         ps |= EMIPS_SR_RST;
    101  1.1     pooka         SetPsr(ps);
    102  1.1     pooka     }
    103  1.1     pooka }
    104  1.1     pooka 
    105  1.3  christos static void
    106  1.3  christos halt(int *unused, int howto)
    107  1.1     pooka {
    108  1.1     pooka     /* We must switch to a safe stack! TLB will go down
    109  1.1     pooka      */
    110  1.1     pooka     switch_stack_and_call((void *)howto,real_halt);
    111  1.1     pooka     /* no return, stack lost */
    112  1.1     pooka }
    113  1.1     pooka 
    114  1.1     pooka struct callback cb = {
    115  1.1     pooka     nope,
    116  1.1     pooka     nope,
    117  1.1     pooka     nope,
    118  1.1     pooka     nope,
    119  1.1     pooka     nope,
    120  1.1     pooka     nope,
    121  1.1     pooka     nope,
    122  1.1     pooka     nope,
    123  1.1     pooka     nope,
    124  1.3  christos     getchar,
    125  1.1     pooka     nope,
    126  1.1     pooka     nope,
    127  1.3  christos     printf,
    128  1.1     pooka     nope,
    129  1.1     pooka     nope,
    130  1.1     pooka     nope,
    131  1.1     pooka     nope,
    132  1.1     pooka     nope,
    133  1.1     pooka     nope,
    134  1.1     pooka     nope,
    135  1.1     pooka     nope,
    136  1.1     pooka     nope,
    137  1.1     pooka     nope,
    138  1.1     pooka     nope,
    139  1.1     pooka     nope,
    140  1.1     pooka     nope,
    141  1.1     pooka     nope,
    142  1.1     pooka     nope,
    143  1.1     pooka     nope,
    144  1.1     pooka     nope,
    145  1.1     pooka     nope,
    146  1.1     pooka     nope,
    147  1.1     pooka     getsysid,
    148  1.1     pooka     nope,
    149  1.1     pooka     nope,
    150  1.1     pooka     nope,
    151  1.1     pooka     nope,
    152  1.1     pooka     nope,
    153  1.1     pooka     nope,
    154  1.3  christos     halt
    155  1.1     pooka };
    156  1.1     pooka 
    157  1.1     pooka typedef char *string_t;
    158  1.1     pooka 
    159  1.1     pooka void epmc_halt(void)
    160  1.1     pooka {
    161  1.1     pooka     struct _Pmc *pm = (struct _Pmc *)0xfff00000;
    162  1.1     pooka 
    163  1.1     pooka     pm->SystemPowerDisable = PMCSC_CPU;
    164  1.1     pooka }
    165  1.1     pooka 
    166  1.1     pooka 
    167  1.1     pooka int init_usart(void)
    168  1.1     pooka {
    169  1.1     pooka     struct _Usart *us = (struct _Usart *)0xfff90000;
    170  1.1     pooka 
    171  1.1     pooka     us->Baud = 0x29;
    172  1.1     pooka     us->Control = (USC_RXEN|USC_TXEN|USC_BPC_8|USC_NONE|USC_1STOP|USC_CLKDIV_4);
    173  1.1     pooka     return 1;
    174  1.1     pooka }
    175  1.1     pooka 
    176  1.1     pooka /* Need to scan the PMT for all memory controllers
    177  1.1     pooka  * Actually.. just enough to make the kernel fit but we dont know how big it is
    178  1.1     pooka  */
    179  1.1     pooka 
    180  1.1     pooka /* Common format for SRAM, DDRAM, and FLASH controllers.
    181  1.1     pooka  * Use SRAM decl. and careful about DDRAM that is twice as big.
    182  1.1     pooka  */
    183  1.1     pooka typedef struct _Sram *ram_controller_t;
    184  1.1     pooka # define                RAMBT_TAG   SRAMBT_TAG
    185  1.1     pooka # define                RAMBT_BASE  SRAMBT_BASE
    186  1.1     pooka # define                RAMST_SIZE  SRAMST_SIZE
    187  1.1     pooka 
    188  1.1     pooka int init_memory(void)
    189  1.1     pooka {
    190  1.1     pooka     struct _Pmt *Pmt;
    191  1.1     pooka     ram_controller_t Ram, Ours, First;
    192  1.1     pooka     uint32_t base, addr, moi = (uint32_t)(&init_memory) & 0x3ffff000;
    193  1.1     pooka     size_t size;
    194  1.1     pooka     uint16_t tag;
    195  1.1     pooka     int nsr, ndr, nfl;
    196  1.1     pooka 
    197  1.1     pooka     /* Make three passes.
    198  1.1     pooka      * First find which controller we are running under, cuz we cant touch it.
    199  1.1     pooka      * Then remap every RAM segment around it.
    200  1.1     pooka      * Then make sure FLASH segments do not overlap RAM.
    201  1.1     pooka      */
    202  1.1     pooka 
    203  1.1     pooka     nsr = ndr = nfl = 0;
    204  1.1     pooka     First = Ours = NULL;
    205  1.1     pooka     base = ~0;
    206  1.1     pooka     for (Pmt = ThePmt;;Pmt--) {
    207  1.1     pooka         tag = Pmt->Tag;
    208  1.1     pooka         //printf("PMT @%x tag=%x\n",Pmt,tag);
    209  1.1     pooka         switch (tag) {
    210  1.1     pooka         case PMTTAG_END_OF_TABLE:
    211  1.1     pooka             goto DoneFirst;
    212  1.1     pooka         case PMTTAG_SRAM:
    213  1.1     pooka         case PMTTAG_DDRAM:
    214  1.1     pooka         case PMTTAG_FLASH:
    215  1.1     pooka             Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
    216  1.1     pooka             /* Scan the whole segment */
    217  1.1     pooka             for (;;) {
    218  1.1     pooka                 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
    219  1.1     pooka                 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
    220  1.1     pooka                     break;
    221  1.1     pooka                 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
    222  1.1     pooka                 if ((tag != PMTTAG_FLASH) && (addr < base)) {
    223  1.1     pooka                     base = addr;
    224  1.1     pooka                     First = Ram;
    225  1.1     pooka                 }
    226  1.1     pooka                 size = Ram->Control & RAMST_SIZE;
    227  1.1     pooka                 if ((moi >= addr) && (moi < (addr + size))) {
    228  1.1     pooka                     Ours = Ram;
    229  1.1     pooka                 }
    230  1.1     pooka                 /* Next one.. and count them */
    231  1.1     pooka                 Ram++;
    232  1.1     pooka                 switch (tag) {
    233  1.1     pooka                 case PMTTAG_SRAM:
    234  1.1     pooka                     nsr++;
    235  1.1     pooka                     break;
    236  1.1     pooka                 case PMTTAG_FLASH:
    237  1.1     pooka                     nfl++;
    238  1.1     pooka                     break;
    239  1.1     pooka                 case PMTTAG_DDRAM:
    240  1.1     pooka                     Ram++; /* yeach */
    241  1.1     pooka                     ndr++;
    242  1.1     pooka                     break;
    243  1.1     pooka                 }
    244  1.1     pooka             }
    245  1.1     pooka             break;
    246  1.1     pooka         default:
    247  1.1     pooka             break;
    248  1.1     pooka         }
    249  1.1     pooka     }
    250  1.1     pooka 
    251  1.1     pooka     /* Make sure we know */
    252  1.1     pooka  DoneFirst:
    253  1.1     pooka     if ((First == NULL) || (Ours == NULL)) {
    254  1.3  christos         printf("Bad memory layout (%p, %p), wont work.\n", First, Ours);
    255  1.1     pooka         return 0;
    256  1.1     pooka     }
    257  1.1     pooka 
    258  1.1     pooka     /* Second pass now */
    259  1.1     pooka     base += First->BaseAddressAndTag & RAMBT_BASE;
    260  1.1     pooka     for (Pmt = ThePmt;;Pmt--) {
    261  1.1     pooka         tag = Pmt->Tag;
    262  1.1     pooka         //printf("PMT @%x tag=%x\n",Pmt,tag);
    263  1.1     pooka         switch (tag) {
    264  1.1     pooka         case PMTTAG_END_OF_TABLE:
    265  1.1     pooka             goto DoneSecond;
    266  1.1     pooka         case PMTTAG_SRAM:
    267  1.1     pooka         case PMTTAG_DDRAM:
    268  1.1     pooka         case PMTTAG_FLASH:
    269  1.1     pooka             Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
    270  1.1     pooka             /* Scan the whole segment */
    271  1.1     pooka             for (;;) {
    272  1.1     pooka                 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
    273  1.1     pooka                 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
    274  1.1     pooka                     break;
    275  1.1     pooka                 /* Leave us alone */
    276  1.1     pooka                 if (Ram == Ours)
    277  1.1     pooka                     goto Next;
    278  1.1     pooka                 /* Leave the first alone too */
    279  1.1     pooka                 if (Ram == First)
    280  1.1     pooka                     goto Next;
    281  1.1     pooka                 /* We do FLASH next round */
    282  1.1     pooka                 if (tag == PMTTAG_FLASH)
    283  1.1     pooka                     goto Next;
    284  1.1     pooka 
    285  1.1     pooka                 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
    286  1.1     pooka                 size = Ram->Control & RAMST_SIZE;
    287  1.1     pooka 
    288  1.1     pooka                 /* Dont make it overlap with us */
    289  1.1     pooka                 if ((moi >= base) && (moi < (base + size)))
    290  1.1     pooka                     base += Ours->Control & RAMST_SIZE;
    291  1.1     pooka 
    292  1.1     pooka                 if (addr != base) {
    293  1.1     pooka                     printf("remapping %x+%x to %x\n", addr, size, base);
    294  1.1     pooka                     Ram->BaseAddressAndTag = base;
    295  1.1     pooka                 }
    296  1.1     pooka                 base += size;
    297  1.1     pooka 
    298  1.1     pooka             Next:
    299  1.1     pooka                 Ram++;
    300  1.1     pooka                 if (tag == PMTTAG_DDRAM) Ram++; /* yeach */
    301  1.1     pooka             }
    302  1.1     pooka             break;
    303  1.1     pooka         default:
    304  1.1     pooka             break;
    305  1.1     pooka         }
    306  1.1     pooka     }
    307  1.1     pooka  DoneSecond:
    308  1.1     pooka 
    309  1.1     pooka     /* Third pass now: FLASH */
    310  1.1     pooka     for (Pmt = ThePmt;;Pmt--) {
    311  1.1     pooka         tag = Pmt->Tag;
    312  1.1     pooka         //printf("PMT @%x tag=%x\n",Pmt,tag);
    313  1.1     pooka         switch (tag) {
    314  1.1     pooka         case PMTTAG_END_OF_TABLE:
    315  1.1     pooka             goto DoneThird;
    316  1.1     pooka         case PMTTAG_FLASH:
    317  1.1     pooka             Ram = (ram_controller_t)(Pmt->TopOfPhysicalAddress << 16);
    318  1.1     pooka             /* Scan the whole segment */
    319  1.1     pooka             for (;;Ram++) {
    320  1.1     pooka                 //printf("RAM @%x tag=%x ctl=%x\n", Ram, Ram->BaseAddressAndTag,Ram->Control);
    321  1.1     pooka                 if (tag != (Ram->BaseAddressAndTag & RAMBT_TAG))
    322  1.1     pooka                     break;
    323  1.1     pooka                 /* Leave us alone */
    324  1.1     pooka                 if (Ram == Ours)
    325  1.1     pooka                     continue;
    326  1.1     pooka 
    327  1.1     pooka                 addr = Ram->BaseAddressAndTag & RAMBT_BASE;
    328  1.1     pooka                 size = Ram->Control & RAMST_SIZE;
    329  1.1     pooka 
    330  1.1     pooka                 /* No need to move if it does not overlap RAM */
    331  1.1     pooka                 if (addr >= base)
    332  1.1     pooka                     continue;
    333  1.1     pooka 
    334  1.1     pooka                 /* Ahi */
    335  1.1     pooka                 printf("remapping FLASH %x+%x to %x\n", addr, size, base);
    336  1.1     pooka                 Ram->BaseAddressAndTag = base;
    337  1.1     pooka                 base += size;
    338  1.1     pooka             }
    339  1.1     pooka             break;
    340  1.1     pooka         default:
    341  1.1     pooka             break;
    342  1.1     pooka         }
    343  1.1     pooka     }
    344  1.1     pooka DoneThird:
    345  1.1     pooka     return (nfl<<16) | (nsr << 8) | (ndr << 0);
    346  1.1     pooka }
    347  1.1     pooka 
    348  1.1     pooka u_int startjump[2];
    349  1.1     pooka u_int exceptioncode[(0x200-0x080)/4]; /* Change if ExceptionHandlerEnd changes */
    350  1.1     pooka 
    351  1.1     pooka void save_locore(void)
    352  1.1     pooka {
    353  1.1     pooka     memcpy(startjump,start,sizeof startjump);
    354  1.1     pooka     memcpy(exceptioncode,ExceptionHandler,sizeof exceptioncode);
    355  1.1     pooka }
    356  1.1     pooka 
    357  1.1     pooka void restore_locore(void)
    358  1.1     pooka {
    359  1.1     pooka     memcpy(start,startjump,sizeof startjump);
    360  1.1     pooka     memcpy(ExceptionHandler,exceptioncode,sizeof exceptioncode);
    361  1.1     pooka     /* BUGBUG flush icache */
    362  1.1     pooka }
    363  1.1     pooka 
    364  1.1     pooka void call_kernel(uint32_t addr, char *kname, char *kargs, u_int bim, char *bip)
    365  1.1     pooka {
    366  1.1     pooka     int argc = 0;
    367  1.1     pooka     string_t argv[3];
    368  1.1     pooka     int code = PROM_MAGIC;
    369  1.1     pooka     struct callback * cv = &cb;
    370  1.1     pooka 
    371  1.1     pooka     /* Safeguard ourselves */
    372  1.1     pooka     save_locore();
    373  1.1     pooka 
    374  1.1     pooka     if (kargs == NULL) kargs = "";
    375  1.1     pooka     argv[0] = kname;
    376  1.1     pooka     argv[1] = kargs;
    377  1.1     pooka     argv[2] = NULL;
    378  1.1     pooka     argc = 2;
    379  1.1     pooka 
    380  1.1     pooka     TRACE(("Geronimo(%x,%s %s)!\n",addr,kname,kargs));
    381  1.1     pooka     ((void(*)(int,char**,int,struct callback *,u_int,char*))addr)
    382  1.1     pooka            (argc,argv,code,cv,bim,bip);
    383  1.1     pooka }
    384  1.1     pooka 
    385