diff --git a/sys/arch/arm32/riscpc/rpc_machdep.c b/sys/arch/arm32/riscpc/rpc_machdep.c index 800a437ad27e..23d703a34305 100644 --- a/sys/arch/arm32/riscpc/rpc_machdep.c +++ b/sys/arch/arm32/riscpc/rpc_machdep.c @@ -1,6 +1,7 @@ -/* $NetBSD: rpc_machdep.c,v 1.34 2000/06/26 14:20:38 mrg Exp $ */ +/* $NetBSD: rpc_machdep.c,v 1.35 2001/02/18 00:59:33 reinoud Exp $ */ /* + * Copyright (c) 2000-2001 Reinoud Zandijk. * Copyright (c) 1994-1998 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. @@ -40,14 +41,16 @@ * * Machine dependant functions for kernel setup * - * This file needs a lot of work. + * This file still needs a lot of work * * Created : 17/09/94 + * Updated for new bootloader 22/10/00 */ #include "opt_cputypes.h" #include "opt_ddb.h" #include "opt_pmap_debug.h" +#include "opt_compat_old_bootloader.h" #include #include @@ -90,7 +93,11 @@ * on where the ROM appears when you turn the MMU off. */ -u_int cpu_reset_address = 0; +#define VERBOSE_INIT_ARM + +u_int cpu_reset_address = 0x3800000; /* XXX for rev0 RiscPC600 */ + +#define MAX_BOOT_STRING 0xff /* Define various stack sizes in pages */ #define IRQ_STACK_SIZE 1 @@ -103,13 +110,21 @@ u_int cpu_reset_address = 0; BootConfig bootconfig; /* Boot config storage */ videomemory_t videomemory; /* Video memory descriptor */ +/* static char bootargs[MAX_BOOT_STRING + 1]; */ +char *boot_args = NULL; +char *boot_file = NULL; vm_offset_t physical_start; vm_offset_t physical_freestart; vm_offset_t physical_freeend; vm_offset_t physical_end; +vm_offset_t dma_range_begin; +vm_offset_t dma_range_end; + u_int free_pages; +vm_offset_t pagetables_start; int physmem = 0; +vm_offset_t memoryblock_end; #ifndef PMAP_STATIC_L1S int max_processes = 64; /* Default number */ @@ -128,9 +143,6 @@ pv_addr_t kernelstack; pv_addr_t hydrascratch; #endif /* NHYDRABUS */ -char *boot_args = NULL; -char *boot_file = NULL; - vm_offset_t msgbufphys; extern u_int data_abort_handler_address; @@ -195,6 +207,7 @@ void parse_rpc_bootargs __P((char *args)); extern void dumpsys __P((void)); extern void hydrastop __P((void)); + /* * void cpu_reboot(int howto, char *bootstr) * @@ -330,6 +343,7 @@ cpu_reboot(howto, bootstr) /*NOTREACHED*/ } + /* * u_int initarm(BootConfig *bootconf) * @@ -344,6 +358,860 @@ cpu_reboot(howto, bootstr) * Relocating the kernel to the bottom of physical memory */ +/* + * this part is completely rewritten for the new bootloader ... It features + * a flat memory map with a mapping comparable to the EBSA arm32 machine + * to boost the portability and likeness of the code + */ + +/* + * Mapping table for core kernel memory. This memory is mapped at init + * time with section mappings. + * + * XXX One big assumption in the current architecture seems that the kernel is + * XXX supposed to be mapped into bootconfig.dram[0], so the bootloader will + * XXX put other area's at the end when deciding to move the kernel to a + * XXX different dram block. + */ + +#define ONE_MB 0x100000 + +struct l1_sec_map { + vm_offset_t va; + vm_offset_t pa; + vm_size_t size; + int flags; +} l1_sec_table[] = { + /* Map 1Mb section for VIDC20 */ + { VIDC_BASE, VIDC_HW_BASE, + ONE_MB, 0 }, + /* Map 1Mb section from IOMD */ + { IOMD_BASE, IOMD_HW_BASE, + ONE_MB, 0 }, + /* Map 1Mb of COMBO (and module space) */ + { IO_BASE, IO_HW_BASE, + ONE_MB, 0 }, + { 0, 0, 0, 0 } +}; + + +/* + * temporary compat stuff + * XXX delete me as soon as posible + */ + +#ifdef COMPAT_OLD_BOOTLOADER + +u_int initarm_new_bootloader __P((BootConfig *bootconf)); +u_int initarm_old_bootloader __P((BootConfig *bootconf)); + +u_int +initarm(bootconf) + BootConfig *bootconf; +{ + if (bootconf->magic == BOOTCONFIG_MAGIC) + return initarm_new_bootloader(bootconf); + else + return initarm_old_bootloader(bootconf); +} + +#else +# define initarm(a) initarm_new_bootloader(a) +#endif + +/* + * The new bootloader initarm ... should be renamed to initarm when the old + * bootloader compatibility is removed + */ +u_int +initarm_new_bootloader(bootconf) + BootConfig *bootconf; +{ + int loop; + int loop1; + u_int logical; + u_int kerneldatasize; + u_int l1pagetable; + u_int l2pagetable; + extern char page0[], page0_end[]; + struct exec *kernexec = (struct exec *)KERNEL_TEXT_BASE; + int id; + pv_addr_t kernel_l1pt; + pv_addr_t kernel_ptpt; + + /* + * Heads up ... Setup the CPU / MMU / TLB functions + */ + set_cpufuncs(); + + /* Copy the boot configuration structure */ + bootconfig = *bootconf; + + /* + * Initialise the video memory descriptor + * + * Note: all references to the video memory virtual/physical address + * should go via this structure. + */ + + /* Hardwire it on the place the bootloader tells us */ + videomemory.vidm_vbase = bootconfig.display_start; + videomemory.vidm_pbase = bootconfig.display_phys; + videomemory.vidm_size = bootconfig.display_size; + if (bootconfig.vram[0].pages) + videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; + else + videomemory.vidm_type = VIDEOMEM_TYPE_DRAM + ; + + /* + * Initialise the physical console + * This is done in main() but for the moment we do it here so that + * we can use printf in initarm() before main() has been called. + */ + consinit(); + + /* + * Initialise the diagnostic serial console + * This allows a means of generating output during initarm(). + * Once all the memory map changes are complete we can call consinit() + * and not have to worry about things moving. + */ +/* fcomcnattach(DC21285_ARMCSR_BASE, comcnspeed, comcnmode);*/ + /* XXX snif .... i am still not able to this */ + + + /* Talk to the user */ + printf("NetBSD/arm32 booting ... \n"); + + /* Tell the user if his boot loader is too old */ + if (bootconfig.magic > BOOTCONFIG_MAGIC) { + printf("\nDETECTED AN OLD BOOTLOADER. PLEASE UPGRADE IT\n\n"); + delay(5000000); + } + + printf("Kernel loaded from file %s\n", bootconfig.kernelname); + printf("Kernel arg string (@%p) %s\n", (void *) bootconfig.argvirtualbase, (char *)bootconfig.argvirtualbase); + printf("\nBoot configuration structure reports the following memory\n"); + + /* + * We have the following memory map (derived from EBSA) + * + * virtual address == physical address apart from the areas: + * 0x00000000 -> 0x000fffff which is mapped to + * top 1MB of physical memory + * 0xf0000000 -> 0xf0ffffff wich is mapped to + * physical address 0x01000000 -> 0x01ffffff (DRAM0a, dram[0]) + * + * This means that the kernel is mapped suitably for continuing + * execution, all I/O is mapped 1:1 virtual to physical and + * physical memory is accessable. + * + * The initarm() has the responcibility for creating the kernel + * page tables. + * It must also set up various memory pointers that are used + * by pmap etc. + */ + + printf(" DRAM block 0a at %08x size %08x DRAM block 0b at %08x size %08x\n\r", + bootconfig.dram[0].address, + bootconfig.dram[0].pages * bootconfig.pagesize, + bootconfig.dram[1].address, + bootconfig.dram[1].pages * bootconfig.pagesize); + printf(" DRAM block 1a at %08x size %08x DRAM block 1b at %08x size %08x\n\r", + bootconfig.dram[2].address, + bootconfig.dram[2].pages * bootconfig.pagesize, + bootconfig.dram[3].address, + bootconfig.dram[3].pages * bootconfig.pagesize); + printf(" VRAM block 0 at %08x size %08x\n\r", + bootconfig.vram[0].address, + bootconfig.vram[0].pages * bootconfig.pagesize); + +/* printf(" videomem: VA=%08x PA=%08x\n", videomemory.vidm_vbase, videomemory.vidm_pbase);*/ + + /* Check to make sure the page size is correct */ + if (NBPG != bootconfig.pagesize) + panic("Page size is not %d bytes\n", NBPG); + +/** START OF REAL NEW STUFF */ + + /* Check if we are having the right kernel */ + id = ReadByte(IOMD_HW_BASE + (IOMD_ID0 << 2)) + | (ReadByte(IOMD_HW_BASE + (IOMD_ID1 << 2)) << 8); + switch (id) { + case ARM7500_IOC_ID: +#ifndef CPU_ARM7500 + panic("Encountered ARM7500 IOMD but no ARM7500 kernel support"); +#endif /* CPU_ARM7500 */ + break; + case RPC600_IOMD_ID: +#ifdef CPU_ARM7500 + panic("Encountered ARM6/7 IOMD and ARM7500 kernel support"); +#endif /* CPU_ARM7500 */ + break; + } + + /* process arguments */ + process_kernel_args(); + + + /* Now set up the page tables for the kernel ... this part is copied + * in a (modified?) way from the EBSA machine port.... + */ + +#ifdef VERBOSE_INIT_ARM + printf("Allocating page tables\n"); +#endif + /* + * Set up the variables that define the availablilty of physcial + * memory + */ + physical_start = bootconfig.dram[0].address; + + physical_end = 0; + for (loop = 0, physmem = 0; loop < bootconfig.dramblocks; ++loop) { + memoryblock_end = bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG; + if (memoryblock_end > physical_end) physical_end = memoryblock_end; + physmem += bootconfig.dram[loop].pages; + }; + physical_freestart = physical_start; + free_pages = bootconfig.drampages; + physical_freeend = physical_end; + + /* constants for now, but might be changed/configured */ + dma_range_begin = (vm_offset_t) physical_start; + dma_range_end = (vm_offset_t) MIN(physical_end, 512*1024*1024); +/* XXX HACK HACK XXX */ +/* dma_range_end = 0x18000000; */ + + /* AHUM !! set this variable ... it was set up in the old 1st stage bootloader */ + kerneldatasize = bootconfig.kernsize + bootconfig.argsize; + + /* Update the address of the first free page of physical memory */ + physical_freestart += bootconfig.kernsize + bootconfig.argsize + bootconfig.scratchsize; + free_pages -= (physical_freestart - physical_start) / NBPG; + + /* Define a macro to simplify memory allocation */ +#define valloc_pages(var, np) \ + alloc_pages((var).pv_pa, (np)); \ + (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; + +#define alloc_pages(var, np) \ + (var) = physical_freestart; \ + physical_freestart += ((np) * NBPG); \ + free_pages -= (np); \ + memset((char *)(var), 0, ((np) * NBPG)); + + loop1 = 0; + kernel_l1pt.pv_pa = 0; + for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { + /* Are we 16KB aligned for an L1 ? */ + if ((physical_freestart & (PD_SIZE - 1)) == 0 + && kernel_l1pt.pv_pa == 0) { + valloc_pages(kernel_l1pt, PD_SIZE / NBPG); + } else { + alloc_pages(kernel_pt_table[loop1], PT_SIZE / NBPG); + ++loop1; + } + } + + +#ifdef DIAGNOSTIC + /* This should never be able to happen but better confirm that. */ + if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (PD_SIZE-1)) != 0) + panic("initarm: Failed to align the kernel page directory\n"); +#endif + + /* + * Allocate a page for the system page mapped to V0x00000000 + * This page will just contain the system vectors and can be + * shared by all processes. + */ + alloc_pages(systempage.pv_pa, 1); + + /* Allocate a page for the page table to map kernel page tables*/ + valloc_pages(kernel_ptpt, PT_SIZE / NBPG); + + /* Allocate stacks for all modes */ + valloc_pages(irqstack, IRQ_STACK_SIZE); + valloc_pages(abtstack, ABT_STACK_SIZE); + valloc_pages(undstack, UND_STACK_SIZE); + valloc_pages(kernelstack, UPAGES); + +#ifdef VERBOSE_INIT_ARM + printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, irqstack.pv_va); + printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, abtstack.pv_va); + printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, undstack.pv_va); + printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, kernelstack.pv_va); +#endif + + alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / NBPG); + +#ifdef CPU_SA110 + /* + * XXX totally stuffed hack to work round problems introduced + * in recent versions of the pmap code. Due to the calls used there + * we cannot allocate virtual memory during bootstrap. + */ + sa110_cc_base = (KERNEL_BASE + (physical_freestart - physical_start) + + (CPU_SA110_CACHE_CLEAN_SIZE - 1)) + & ~(CPU_SA110_CACHE_CLEAN_SIZE - 1); +#endif /* CPU_SA110 */ + + /* + * Ok we have allocated physical pages for the primary kernel + * page tables + */ + +#ifdef VERBOSE_INIT_ARM + printf("Creating L1 page table\n"); +#endif + + /* + * Now we start construction of the L1 page table + * We start by mapping the L2 page tables into the L1. + * This means that we can replace L1 mappings later on if necessary + */ + l1pagetable = kernel_l1pt.pv_pa; + + /* Map the L2 pages tables in the L1 page table */ + map_pagetable(l1pagetable, 0x00000000, + kernel_pt_table[KERNEL_PT_SYS]); + map_pagetable(l1pagetable, KERNEL_BASE, + kernel_pt_table[KERNEL_PT_KERNEL]); + for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; ++loop) + map_pagetable(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, + kernel_pt_table[KERNEL_PT_VMDATA + loop]); + map_pagetable(l1pagetable, PROCESS_PAGE_TBLS_BASE, + kernel_ptpt.pv_pa); + map_pagetable(l1pagetable, VMEM_VBASE, + kernel_pt_table[KERNEL_PT_VMEM]); + + +#ifdef VERBOSE_INIT_ARM + printf("Mapping kernel\n"); +#endif + + /* Now we fill in the L2 pagetable for the kernel code/data */ + l2pagetable = kernel_pt_table[KERNEL_PT_KERNEL]; + + if (N_GETMAGIC(kernexec[0]) == ZMAGIC) { + /* + * This is a work around for a recent problem that occurred + * with ARM 610 processors and some ARM 710 processors + * Other ARM 710 and StrongARM processors don't have a problem. + */ +#if defined(CPU_ARM6) || defined(CPU_ARM7) + logical = map_chunk(0, l2pagetable, KERNEL_TEXT_BASE, + physical_start, kernexec->a_text, + AP_KRW, PT_CACHEABLE); +#else /* CPU_ARM6 || CPU_ARM7 */ + logical = map_chunk(0, l2pagetable, KERNEL_TEXT_BASE, + physical_start, kernexec->a_text, + AP_KR, PT_CACHEABLE); +#endif /* CPU_ARM6 || CPU_ARM7 */ + logical += map_chunk(0, l2pagetable, KERNEL_TEXT_BASE + logical, + physical_start + logical, kerneldatasize - kernexec->a_text, + AP_KRW, PT_CACHEABLE); + } else + map_chunk(0, l2pagetable, KERNEL_TEXT_BASE, + physical_start, kerneldatasize, + AP_KRW, PT_CACHEABLE) + ; + + +#ifdef VERBOSE_INIT_ARM + printf("Constructing L2 page tables\n"); +#endif + + /* Map the stack pages */ + map_chunk(0, l2pagetable, irqstack.pv_va, irqstack.pv_pa, + IRQ_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE); + map_chunk(0, l2pagetable, abtstack.pv_va, abtstack.pv_pa, + ABT_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE); + map_chunk(0, l2pagetable, undstack.pv_va, undstack.pv_pa, + UND_STACK_SIZE * NBPG, AP_KRW, PT_CACHEABLE); + map_chunk(0, l2pagetable, kernelstack.pv_va, kernelstack.pv_pa, + UPAGES * NBPG, AP_KRW, PT_CACHEABLE); + map_chunk(0, l2pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, + PD_SIZE, AP_KRW, 0); + + /* Map the page table that maps the kernel pages */ + map_entry_nc(l2pagetable, kernel_ptpt.pv_pa - physical_start, + kernel_ptpt.pv_pa); + + + /* Now we fill in the L2 pagetable for the VRAM */ + /* + * Current architectures mean that the VRAM is always in 1 continuous + * bank. + * This means that we can just map the 2 meg that the VRAM would occupy. + * In theory we don't need a page table for VRAM, we could section map + * it but we would need the page tables if DRAM was in use. + * XXX please map two adjacent virtual areas to ONE physical area + */ + l2pagetable = kernel_pt_table[KERNEL_PT_VMEM]; + + map_chunk(0, l2pagetable, VMEM_VBASE, videomemory.vidm_pbase, + videomemory.vidm_size, AP_KRW, PT_CACHEABLE); + map_chunk(0, l2pagetable, VMEM_VBASE + videomemory.vidm_size, + videomemory.vidm_pbase, videomemory.vidm_size, + AP_KRW, PT_CACHEABLE); + + + /* + * Map entries in the page table used to map PTE's + * Basically every kernel page table gets mapped here + */ + /* The -2 is slightly bogus, it should be -log2(sizeof(pt_entry_t)) */ + l2pagetable = kernel_ptpt.pv_pa; + map_entry_nc(l2pagetable, (KERNEL_BASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_KERNEL]); + map_entry_nc(l2pagetable, (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)), + kernel_ptpt.pv_pa); + map_entry_nc(l2pagetable, (VMEM_VBASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMEM]); + map_entry_nc(l2pagetable, (0x00000000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_SYS]); + for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; ++loop) { + map_entry_nc(l2pagetable, ((KERNEL_VM_BASE + + (loop * 0x00400000)) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA + loop]); + } + + /* + * Map the system page in the kernel page table for the bottom 1Meg + * of the virtual memory map. + */ + l2pagetable = kernel_pt_table[KERNEL_PT_SYS]; + map_entry(l2pagetable, 0x0000000, systempage.pv_pa); + + /* Map the core memory needed before autoconfig */ + loop = 0; + while (l1_sec_table[loop].size) { + vm_size_t sz; + +#ifdef VERBOSE_INIT_ARM + printf("%08lx -> %08lx @ %08lx\n", l1_sec_table[loop].pa, + l1_sec_table[loop].pa + l1_sec_table[loop].size - 1, + l1_sec_table[loop].va); +#endif + for (sz = 0; sz < l1_sec_table[loop].size; sz += L1_SEC_SIZE) + map_section(l1pagetable, l1_sec_table[loop].va + sz, + l1_sec_table[loop].pa + sz, + l1_sec_table[loop].flags); + ++loop; + } + + /* + * Now we have the real page tables in place so we can switch to them. + * Once this is done we will be running with the REAL kernel page tables. + */ + + /* Switch tables */ +#ifdef VERBOSE_INIT_ARM + printf("switching to new L1 page table\n"); +#endif + + setttb(kernel_l1pt.pv_pa); + + /* + * We must now clean the cache again.... + * Cleaning may be done by reading new data to displace any + * dirty data in the cache. This will have happened in setttb() + * but since we are boot strapping the addresses used for the read + * may have just been remapped and thus the cache could be out + * of sync. A re-clean after the switch will cure this. + * After booting there are no gross reloations of the kernel thus + * this problem will not occur after initarm(). + */ + cpu_cache_cleanID(); + + /* if there is support for a serial console ...we should now reattach it */ + /* fcomcndetach();*/ + + + /* + * Reflect videomemory relocation in the videomemory structure + * and reinit console + */ + if (bootconfig.vram[0].pages == 0) { + videomemory.vidm_vbase = VMEM_VBASE; + } else { + videomemory.vidm_vbase = VMEM_VBASE; + bootconfig.display_start = VMEM_VBASE; + }; + physcon_display_base(VMEM_VBASE); + vidcconsole_reinit(); + +#ifdef VERBOSE_INIT_ARM + printf("running on the new L1 page table!\n"); +#endif + printf("done.\n"); + + /* Right set up the vectors at the bottom of page 0 */ + memcpy((char *)0x00000000, page0, page0_end - page0); + + /* We have modified a text page so sync the icache */ + cpu_cache_syncI_rng(0, page0_end - page0); + + /* + * Pages were allocated during the secondary bootstrap for the + * stacks for different CPU modes. + * We must now set the r13 registers in the different CPU modes to + * point to these stacks. + * Since the ARM stacks use STMFD etc. we must set r13 to the top end + * of the stack memory. + */ + printf("init subsystems: stacks "); + console_flush(); + + set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * NBPG); + set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * NBPG); + set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * NBPG); +#ifdef PMAP_DEBUG + if (pmap_debug_level >= 0) + printf("kstack V%08lx P%08lx\n", kernelstack.pv_va, + kernelstack.pv_pa); +#endif /* PMAP_DEBUG */ + + /* + * Well we should set a data abort handler. + * Once things get going this will change as we will need a proper + * handler. Until then we will use a handler that just panics but + * tells us why. + * Initialisation of the vectors will just panic on a data abort. + * This just fills in a slighly better one. + */ + printf("vectors "); + data_abort_handler_address = (u_int)data_abort_handler; + prefetch_abort_handler_address = (u_int)prefetch_abort_handler; + undefined_handler_address = (u_int)undefinedinstruction_bounce; + console_flush(); + + + /* At last ! + * We now have the kernel in physical memory from the bottom upwards. + * Kernel page tables are physically above this. + * The kernel is mapped to 0xf0000000 + * The kernel data PTs will handle the mapping of 0xf1000000-0xf5ffffff (80 Mb) + * 2Meg of VRAM is mapped to 0xf7000000 + * The page tables are mapped to 0xefc00000 + * The IOMD is mapped to 0xf6000000 + * The VIDC is mapped to 0xf6100000 + * The IOMD/VIDC could be pushed up higher but i havent got sufficient + * documentation to do so; the addresses are not parametized yet and hard + * to read... better fix this before; its pretty unforgiving. + */ + + /* Initialise the undefined instruction handlers */ + printf("undefined "); + undefined_init(); + console_flush(); + + /* Boot strap pmap telling it where the kernel page table is */ + printf("pmap "); + pmap_bootstrap(kernel_l1pt.pv_va, kernel_ptpt); + console_flush(); + + /* Setup the IRQ system */ + printf("irq "); + console_flush(); + irq_init(); + printf("done.\n"); + + if (cmos_read(RTC_ADDR_REBOOTCNT) > 0) + printf("Warning: REBOOTCNT = %d\n", + cmos_read(RTC_ADDR_REBOOTCNT)); + +#ifdef CPU_SA110 + if (cputype == ID_SA110) + rpc_sa110_cc_setup(); +#endif /* CPU_SA110 */ + +#ifdef IPKDB + /* Initialise ipkdb */ + ipkdb_init(); + if (boothowto & RB_KDB) + ipkdb_connect(0); +#endif /* NIPKDB */ + +#ifdef DDB + printf("ddb: "); + db_machine_init(); + { + extern int end; + extern int *esym; + + ddb_init(*(int *)&end, ((int *)&end) + 1, esym); + } + + if (boothowto & RB_KDB) + Debugger(); +#endif /* DDB */ + + /* We return the new stack pointer address */ + return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); +} + +static void +process_kernel_args(void) +{ + char *args; + + /* Ok now we will check the arguments for interesting parameters. */ + args = (char *)bootconfig.argvirtualbase; + boothowto = 0; + + /* Only arguments itself are passed from the new bootloader */ + while (*args == ' ') + ++args; + + boot_args = args; + parse_mi_bootargs(boot_args); + parse_rpc_bootargs(boot_args); +} + + +void +parse_rpc_bootargs(args) + char *args; +{ + int integer; + + if (get_bootconf_option(args, "videodram", BOOTOPT_TYPE_INT, &integer)) { + videodram_size = integer; + /* Round to 4K page */ + videodram_size *= 1024; + videodram_size = round_page(videodram_size); + if (videodram_size > 1024*1024) + videodram_size = 1024*1024; + }; + +#if 0 + /* XXX this I would rather have in the new bootconfig structure */ + if (get_bootconf_option(args, "kinetic", BOOTOPT_TYPE_BOOLEAN, &integer)) { + bootconfig.RPC_kinetic_card_support = 1; + }; +#endif +} + + +#if 0 +/* XXXX I think this code can be deleted .... */ +/* + * Ok these are some development functions. They map blocks of memory + * into the video ram virtual memory. + * The idea is to follow this with a call to the vidc device to + * reinitialise the vidc20 for the new video ram. + * Only meaning full if was support VRAM. + */ + +/* Map DRAM into the video memory */ + +int +vmem_mapdram() +{ + u_int l2pagetable; + u_int logical; + + if (videodram_start == 0 || videodram_size == 0) + return(ENOMEM); + + /* flush existing video data */ + cpu_cache_purgeD(); + + /* Get the level 2 pagetable for the video memory */ + l2pagetable = (u_int)pmap_pte(kernel_pmap, + (vm_offset_t)videomemory.vidm_vbase); + + /* Map a block of DRAM into the video memory area */ + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, videodram_start + + logical); + map_entry(l2pagetable, logical + 0x200000, + videodram_start + logical); + } + + /* Flush the TLB so we pick up the new mappings */ + cpu_tlb_flushD(); + + /* Rebuild the video memory descriptor */ + videomemory.vidm_vbase = VMEM_VBASE; + videomemory.vidm_pbase = videodram_start; + videomemory.vidm_type = VIDEOMEM_TYPE_DRAM; + videomemory.vidm_size = videodram_size; + + /* Reinitialise the video system */ +/* video_reinit();*/ + return(0); +} + + +/* Map VRAM into the video memory */ + +int +vmem_mapvram() +{ + u_int l2pagetable; + u_int logical; + + if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) + return(ENOMEM); + + /* flush existing video data */ + cpu_cache_purgeD(); + + /* Get the level 2 pagetable for the video memory */ + l2pagetable = (u_int)pmap_pte(kernel_pmap, + (vm_offset_t)videomemory.vidm_vbase); + + /* Map the VRAM into the video memory area */ + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, bootconfig.vram[0].address + + logical); + map_entry(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + + /* Flush the TLB so we pick up the new mappings */ + cpu_tlb_flushD(); + + /* Rebuild the video memory descriptor */ + videomemory.vidm_vbase = VMEM_VBASE; + videomemory.vidm_pbase = VRAM_BASE; + videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; + videomemory.vidm_size = bootconfig.vram[0].pages * NBPG; + + /* Reinitialise the video system */ +/* video_reinit();*/ + return(0); +} + + +/* Set the cache behaviour for the video memory */ + +int +vmem_cachectl(flag) + int flag; +{ + u_int l2pagetable; + u_int logical; + u_int pa; + + if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) + return(ENOMEM); + + /* Get the level 2 pagetable for the video memory */ + l2pagetable = (u_int)pmap_pte(kernel_pmap, + (vm_offset_t)videomemory.vidm_vbase); + + /* Map the VRAM into the video memory area */ + if (flag == 0) { + printf("Disabling caching and buffering of VRAM\n"); + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry_nc(l2pagetable, logical, + bootconfig.vram[0].address + logical); + map_entry_nc(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + } else if (flag == 1) { + printf("Disabling caching of VRAM\n"); + for (logical = 0; logical < 0x200000; logical += NBPG) { + pa = bootconfig.vram[0].address + logical; + WriteWord(l2pagetable + ((logical >> 10) & 0x00000ffc), + L2_PTE_NC((pa & PG_FRAME), AP_KRW)); + WriteWord(l2pagetable + (((logical+0x200000) >> 10) & 0x00000ffc), + L2_PTE_NC((pa & PG_FRAME), AP_KRW)); + } + } else if (flag == 2) { + printf("Disabling buffering of VRAM\n"); + for (logical = 0; logical < 0x200000; logical += NBPG) { + pa = bootconfig.vram[0].address + logical; + WriteWord(l2pagetable + ((logical >> 10) & 0x00000ffc), + L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW)|PT_C); + WriteWord(l2pagetable + (((logical+0x200000) >> 10) & 0x00000ffc), + L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW)|PT_C); + } + } else { + printf("Enabling caching and buffering of VRAM\n"); + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, + bootconfig.vram[0].address + logical); + map_entry(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + } + + /* clean out any existing cached video data */ + cpu_cache_purgeD(); + + /* Flush the TLB so we pick up the new mappings */ + cpu_tlb_flushD(); + + return(0); +} +#endif + +#ifdef CPU_SA110 + +/* + * For optimal cache cleaning we need two 16K banks of + * virtual address space that NOTHING else will access + * and then we alternate the cache cleaning between the + * two banks. + * The cache cleaning code requires requires 2 banks aligned + * on total size boundry so the banks can be alternated by + * eorring the size bit (assumes the bank size is a power of 2) + */ +extern unsigned int sa110_cache_clean_addr; +extern unsigned int sa110_cache_clean_size; +void +rpc_sa110_cc_setup(void) +{ + int loop; + paddr_t kaddr; + pt_entry_t *pte; + + (void) pmap_extract(kernel_pmap, KERNEL_TEXT_BASE, &kaddr); + for (loop = 0; loop < CPU_SA110_CACHE_CLEAN_SIZE; loop += NBPG) { + pte = pmap_pte(kernel_pmap, (sa110_cc_base + loop)); + *pte = L2_PTE(kaddr, AP_KR); + } + sa110_cache_clean_addr = sa110_cc_base; + sa110_cache_clean_size = CPU_SA110_CACHE_CLEAN_SIZE / 2; +} +#endif /* CPU_SA110 */ + +/* End of machdep.c */ + + +/******************************************************************************* + ******************************************************************************* + ******************************************************************************* + ****************************** Compat stuff *********************************** + ******************************************************************************* + ******************************************************************************* + *******************************************************************************/ + +#ifdef COMPAT_OLD_BOOTLOADER +/* + * u_int initarm_old_bootloader(bootConfig *bootconf) + * + * Reinoud : Only kept here for compatibility reasons.... it really needs to + * go ASAP !!!! + * + * Initial entry point on startup. This gets called before main() is + * entered. + * It should be responcible for setting up everything that must be + * in place when main is called. + * This includes + * Taking a copy of the boot configuration structure. + * Initialising the physical console so characters can be printed. + * Setting up page tables for the kernel + * Relocating the kernel to the bottom of physical memory + */ + /* This routine is frightening mess ! This is what my mind looks like -mark */ /* @@ -355,8 +1223,11 @@ cpu_reboot(howto, bootstr) * kernel to. */ +#undef valloc_pages +#undef alloc_pages + u_int -initarm(bootconf) +initarm_old_bootloader(bootconf) BootConfig *bootconf; { int loop; @@ -423,7 +1294,7 @@ initarm(bootconf) /* Tell the user if his boot loader is too old */ if (bootconfig.magic != BOOTCONFIG_MAGIC) { - printf("\nNO MAGIC NUMBER IN BOOTCONFIG. PLEASE UPGRADE YOUR BOOT LOADER\n\n"); + printf("\n !!! OLD STYLE BOOTLOADER DETECTED !!! PLEASE UPGRADE TO NEW BOOTLOADER ASAP !\n\n"); delay(5000000); } @@ -1154,233 +2025,6 @@ initarm(bootconf) return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); } -static void -process_kernel_args(void) -{ - char *args; - - /* Ok now we will check the arguments for interesting parameters. */ - args = (char *)bootconfig.argvirtualbase; - boothowto = 0; - - /* Skip the first parameter (the boot loader filename) */ - while (*args != ' ' && *args != 0) - ++args; - - while (*args == ' ') - ++args; - - /* Skip the kernel image filename */ - while (*args != ' ' && *args != 0) - ++args; - - while (*args == ' ') - ++args; - - boot_args = args; - parse_mi_bootargs(boot_args); - parse_rpc_bootargs(boot_args); -} - - -void -parse_rpc_bootargs(args) - char *args; -{ - int integer; - - if (get_bootconf_option(args, "videodram", BOOTOPT_TYPE_INT, &integer)) { - videodram_size = integer; - /* Round to 4K page */ - videodram_size *= 1024; - videodram_size = round_page(videodram_size); - if (videodram_size > 1024*1024) - videodram_size = 1024*1024; - } -} - - -/* - * Ok these are some development functions. They map blocks of memory - * into the video ram virtual memory. - * The idea is to follow this with a call to the vidc device to - * reinitialise the vidc20 for the new video ram. - * Only meaning full if was support VRAM. - */ - -/* Map DRAM into the video memory */ - -int -vmem_mapdram() -{ - u_int l2pagetable; - u_int logical; - - if (videodram_start == 0 || videodram_size == 0) - return(ENOMEM); - - /* flush existing video data */ - cpu_cache_purgeD(); - - /* Get the level 2 pagetable for the video memory */ - l2pagetable = (u_int)pmap_pte(kernel_pmap, - (vm_offset_t)videomemory.vidm_vbase); - - /* Map a block of DRAM into the video memory area */ - for (logical = 0; logical < 0x200000; logical += NBPG) { - map_entry(l2pagetable, logical, videodram_start - + logical); - map_entry(l2pagetable, logical + 0x200000, - videodram_start + logical); - } - - /* Flush the TLB so we pick up the new mappings */ - cpu_tlb_flushD(); - - /* Rebuild the video memory descriptor */ - videomemory.vidm_vbase = VMEM_VBASE; - videomemory.vidm_pbase = videodram_start; - videomemory.vidm_type = VIDEOMEM_TYPE_DRAM; - videomemory.vidm_size = videodram_size; - - /* Reinitialise the video system */ -/* video_reinit();*/ - return(0); -} - - -/* Map VRAM into the video memory */ - -int -vmem_mapvram() -{ - u_int l2pagetable; - u_int logical; - - if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) - return(ENOMEM); - - /* flush existing video data */ - cpu_cache_purgeD(); - - /* Get the level 2 pagetable for the video memory */ - l2pagetable = (u_int)pmap_pte(kernel_pmap, - (vm_offset_t)videomemory.vidm_vbase); - - /* Map the VRAM into the video memory area */ - for (logical = 0; logical < 0x200000; logical += NBPG) { - map_entry(l2pagetable, logical, bootconfig.vram[0].address - + logical); - map_entry(l2pagetable, logical + 0x200000, - bootconfig.vram[0].address + logical); - } - - /* Flush the TLB so we pick up the new mappings */ - cpu_tlb_flushD(); - - /* Rebuild the video memory descriptor */ - videomemory.vidm_vbase = VMEM_VBASE; - videomemory.vidm_pbase = VRAM_BASE; - videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; - videomemory.vidm_size = bootconfig.vram[0].pages * NBPG; - - /* Reinitialise the video system */ -/* video_reinit();*/ - return(0); -} - - -/* Set the cache behaviour for the video memory */ - -int -vmem_cachectl(flag) - int flag; -{ - u_int l2pagetable; - u_int logical; - u_int pa; - - if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) - return(ENOMEM); - - /* Get the level 2 pagetable for the video memory */ - l2pagetable = (u_int)pmap_pte(kernel_pmap, - (vm_offset_t)videomemory.vidm_vbase); - - /* Map the VRAM into the video memory area */ - if (flag == 0) { - printf("Disabling caching and buffering of VRAM\n"); - for (logical = 0; logical < 0x200000; logical += NBPG) { - map_entry_nc(l2pagetable, logical, - bootconfig.vram[0].address + logical); - map_entry_nc(l2pagetable, logical + 0x200000, - bootconfig.vram[0].address + logical); - } - } else if (flag == 1) { - printf("Disabling caching of VRAM\n"); - for (logical = 0; logical < 0x200000; logical += NBPG) { - pa = bootconfig.vram[0].address + logical; - WriteWord(l2pagetable + ((logical >> 10) & 0x00000ffc), - L2_PTE_NC((pa & PG_FRAME), AP_KRW)); - WriteWord(l2pagetable + (((logical+0x200000) >> 10) & 0x00000ffc), - L2_PTE_NC((pa & PG_FRAME), AP_KRW)); - } - } else if (flag == 2) { - printf("Disabling buffering of VRAM\n"); - for (logical = 0; logical < 0x200000; logical += NBPG) { - pa = bootconfig.vram[0].address + logical; - WriteWord(l2pagetable + ((logical >> 10) & 0x00000ffc), - L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW)|PT_C); - WriteWord(l2pagetable + (((logical+0x200000) >> 10) & 0x00000ffc), - L2_PTE_NC_NB((pa & PG_FRAME), AP_KRW)|PT_C); - } - } else { - printf("Enabling caching and buffering of VRAM\n"); - for (logical = 0; logical < 0x200000; logical += NBPG) { - map_entry(l2pagetable, logical, - bootconfig.vram[0].address + logical); - map_entry(l2pagetable, logical + 0x200000, - bootconfig.vram[0].address + logical); - } - } - - /* clean out any existing cached video data */ - cpu_cache_purgeD(); - - /* Flush the TLB so we pick up the new mappings */ - cpu_tlb_flushD(); - - return(0); -} - -#ifdef CPU_SA110 - -/* - * For optimal cache cleaning we need two 16K banks of - * virtual address space that NOTHING else will access - * and then we alternate the cache cleaning between the - * two banks. - * The cache cleaning code requires requires 2 banks aligned - * on total size boundry so the banks can be alternated by - * eorring the size bit (assumes the bank size is a power of 2) - */ -extern unsigned int sa110_cache_clean_addr; -extern unsigned int sa110_cache_clean_size; -void -rpc_sa110_cc_setup(void) -{ - int loop; - paddr_t kaddr; - pt_entry_t *pte; - - (void) pmap_extract(kernel_pmap, KERNEL_TEXT_BASE, &kaddr); - for (loop = 0; loop < CPU_SA110_CACHE_CLEAN_SIZE; loop += NBPG) { - pte = pmap_pte(kernel_pmap, (sa110_cc_base + loop)); - *pte = L2_PTE(kaddr, AP_KR); - } - sa110_cache_clean_addr = sa110_cc_base; - sa110_cache_clean_size = CPU_SA110_CACHE_CLEAN_SIZE / 2; -} -#endif /* CPU_SA110 */ +#endif /* End of machdep.c */