netwinder_machdep.c revision 1.61
11.61Suwe/* $NetBSD: netwinder_machdep.c,v 1.61 2006/04/05 00:37:11 uwe Exp $ */ 21.1Smatt 31.1Smatt/* 41.1Smatt * Copyright (c) 1997,1998 Mark Brinicombe. 51.1Smatt * Copyright (c) 1997,1998 Causality Limited. 61.1Smatt * All rights reserved. 71.1Smatt * 81.1Smatt * Redistribution and use in source and binary forms, with or without 91.1Smatt * modification, are permitted provided that the following conditions 101.1Smatt * are met: 111.1Smatt * 1. Redistributions of source code must retain the above copyright 121.1Smatt * notice, this list of conditions and the following disclaimer. 131.1Smatt * 2. Redistributions in binary form must reproduce the above copyright 141.1Smatt * notice, this list of conditions and the following disclaimer in the 151.1Smatt * documentation and/or other materials provided with the distribution. 161.1Smatt * 3. All advertising materials mentioning features or use of this software 171.1Smatt * must display the following acknowledgement: 181.1Smatt * This product includes software developed by Mark Brinicombe 191.1Smatt * for the NetBSD Project. 201.1Smatt * 4. The name of the company nor the name of the author may be used to 211.1Smatt * endorse or promote products derived from this software without specific 221.1Smatt * prior written permission. 231.1Smatt * 241.1Smatt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 251.1Smatt * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 261.1Smatt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 271.1Smatt * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 281.1Smatt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 291.1Smatt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 301.1Smatt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311.1Smatt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321.1Smatt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331.1Smatt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341.1Smatt * SUCH DAMAGE. 351.1Smatt * 361.1Smatt * Machine dependant functions for kernel setup for EBSA285 core architecture 371.1Smatt * using Netwinder firmware 381.1Smatt * 391.1Smatt * Created : 24/11/97 401.1Smatt */ 411.56Slukem 421.56Slukem#include <sys/cdefs.h> 431.61Suwe__KERNEL_RCSID(0, "$NetBSD: netwinder_machdep.c,v 1.61 2006/04/05 00:37:11 uwe Exp $"); 441.1Smatt 451.1Smatt#include "opt_ddb.h" 461.55Suwe#include "opt_ipkdb.h" 471.1Smatt#include "opt_pmap_debug.h" 481.1Smatt 491.1Smatt#include <sys/param.h> 501.1Smatt#include <sys/device.h> 511.1Smatt#include <sys/systm.h> 521.1Smatt#include <sys/kernel.h> 531.1Smatt#include <sys/exec.h> 541.1Smatt#include <sys/proc.h> 551.1Smatt#include <sys/msgbuf.h> 561.1Smatt#include <sys/reboot.h> 571.1Smatt#include <sys/termios.h> 581.46Sragge#include <sys/ksyms.h> 591.1Smatt 601.44Sthorpej#include <uvm/uvm_extern.h> 611.44Sthorpej 621.1Smatt#include <dev/cons.h> 631.1Smatt 641.1Smatt#include <machine/db_machdep.h> 651.1Smatt#include <ddb/db_sym.h> 661.1Smatt#include <ddb/db_extern.h> 671.1Smatt 681.38Sthorpej#include <arm/arm32/machdep.h> 691.38Sthorpej 701.1Smatt#include <machine/bootconfig.h> 711.34Sthorpej#define _ARM32_BUS_DMA_PRIVATE 721.1Smatt#include <machine/bus.h> 731.1Smatt#include <machine/cpu.h> 741.1Smatt#include <machine/frame.h> 751.9Smatt#include <machine/intr.h> 761.14Sthorpej#include <arm/undefined.h> 771.1Smatt 781.1Smatt#include <machine/netwinder_boot.h> 791.3Schris#include <arm/footbridge/dc21285mem.h> 801.3Schris#include <arm/footbridge/dc21285reg.h> 811.1Smatt 821.1Smatt#include "isa.h" 831.55Suwe#include "isadma.h" 841.1Smatt#if NISA > 0 851.1Smatt#include <dev/isa/isareg.h> 861.1Smatt#include <dev/isa/isavar.h> 871.1Smatt#endif 881.1Smatt 891.55Suwe#include "igsfb.h" 901.55Suwe#if NIGSFB > 0 911.55Suwe#include <dev/pci/pcivar.h> 921.55Suwe#include <dev/pci/igsfb_pcivar.h> 931.55Suwe#endif 941.55Suwe 951.55Suwe#include "pckbc.h" 961.55Suwe#if NPCKBC > 0 971.55Suwe#include <dev/ic/i8042reg.h> 981.55Suwe#include <dev/ic/pckbcvar.h> 991.55Suwe#endif 1001.55Suwe 1011.55Suwe#include "com.h" 1021.55Suwe#include <dev/ic/comreg.h> 1031.55Suwe#include <dev/ic/comvar.h> 1041.55Suwe 1051.46Sragge#include "ksyms.h" 1061.46Sragge 1071.8Smattstatic bus_space_handle_t isa_base = (bus_space_handle_t) DC21285_PCI_IO_VBASE; 1081.8Smatt 1091.31Sthorpejbs_protos(generic); 1101.8Smatt 1111.31Sthorpej#define ISA_GETBYTE(r) generic_bs_r_1(0, isa_base, (r)) 1121.31Sthorpej#define ISA_PUTBYTE(r,v) generic_bs_w_1(0, isa_base, (r), (v)) 1131.8Smatt 1141.1Smatt/* 1151.1Smatt * Address to call from cpu_reset() to reset the machine. 1161.1Smatt * This is machine architecture dependant as it varies depending 1171.1Smatt * on where the ROM appears when you turn the MMU off. 1181.1Smatt */ 1191.27Sthorpejstatic void netwinder_reset(void); 1201.52Suweu_int cpu_reset_address; 1211.1Smatt 1221.8Smattu_int dc21285_fclk = 63750000; 1231.1Smatt 1241.1Smatt/* Define various stack sizes in pages */ 1251.1Smatt#define IRQ_STACK_SIZE 1 1261.1Smatt#define ABT_STACK_SIZE 1 1271.1Smatt#ifdef IPKDB 1281.1Smatt#define UND_STACK_SIZE 2 1291.1Smatt#else 1301.1Smatt#define UND_STACK_SIZE 1 1311.1Smatt#endif 1321.1Smatt 1331.1Smattstruct nwbootinfo nwbootinfo; 1341.1SmattBootConfig bootconfig; /* Boot config storage */ 1351.1Smattstatic char bootargs[MAX_BOOT_STRING + 1]; 1361.1Smattchar *boot_args = NULL; 1371.1Smattchar *boot_file = NULL; 1381.1Smatt 1391.1Smattvm_offset_t physical_start; 1401.1Smattvm_offset_t physical_freestart; 1411.1Smattvm_offset_t physical_freeend; 1421.1Smattvm_offset_t physical_end; 1431.1Smattu_int free_pages; 1441.1Smattvm_offset_t pagetables_start; 1451.1Smattint physmem = 0; 1461.1Smatt 1471.1Smatt/*int debug_flags;*/ 1481.1Smatt#ifndef PMAP_STATIC_L1S 1491.1Smattint max_processes = 64; /* Default number */ 1501.1Smatt#endif /* !PMAP_STATIC_L1S */ 1511.1Smatt 1521.1Smatt/* Physical and virtual addresses for some global pages */ 1531.1Smattpv_addr_t systempage; 1541.1Smattpv_addr_t irqstack; 1551.1Smattpv_addr_t undstack; 1561.1Smattpv_addr_t abtstack; 1571.61Suweextern pv_addr_t kernelstack; /* in arm32_machdep.c */ 1581.1Smatt 1591.1Smattvm_offset_t msgbufphys; 1601.1Smatt 1611.1Smattextern u_int data_abort_handler_address; 1621.1Smattextern u_int prefetch_abort_handler_address; 1631.1Smattextern u_int undefined_handler_address; 1641.1Smatt 1651.1Smatt#ifdef PMAP_DEBUG 1661.1Smattextern int pmap_debug_level; 1671.1Smatt#endif 1681.1Smatt 1691.1Smatt#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ 1701.1Smatt#define KERNEL_PT_KERNEL 1 /* Page table for mapping kernel */ 1711.1Smatt#define KERNEL_PT_VMDATA 2 /* Page tables for mapping kernel VM */ 1721.24Schris#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ 1731.1Smatt#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) 1741.1Smatt 1751.21Sthorpejpv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; 1761.50Sthorpej 1771.50Sthorpej#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) 1781.51Sthorpej/* 1791.51Sthorpej * The range 0xf1000000 - 0xfcffffff is available for kernel VM space 1801.51Sthorpej * Footbridge registers and I/O mappings occupy 0xfd000000 - 0xffffffff 1811.51Sthorpej */ 1821.55Suwe#if NIGSFB > 0 1831.55Suwe/* XXX: uwe: map 16 megs at 0xfc000000 for igsfb(4) */ 1841.55Suwe#define KERNEL_VM_SIZE 0x0B000000 1851.55Suwe#else 1861.51Sthorpej#define KERNEL_VM_SIZE 0x0C000000 1871.55Suwe#endif 1881.1Smatt 1891.61Suweextern struct user *proc0paddr; /* in arm32_machdep.c */ 1901.1Smatt 1911.1Smatt/* Prototypes */ 1921.1Smatt 1931.53Suwevoid consinit(void); 1941.53Suwevoid process_kernel_args(char *); 1951.53Suwevoid data_abort_handler(trapframe_t *); 1961.53Suwevoid prefetch_abort_handler(trapframe_t *); 1971.53Suwevoid undefinedinstruction_bounce(trapframe_t *); 1981.1Smatt 1991.1Smatt 2001.1Smatt/* A load of console goo. */ 2011.55Suwe#ifndef CONSDEVNAME 2021.55Suwe# if (NIGSFB > 0) && (NPCKBC > 0) 2031.55Suwe# define CONSDEVNAME "igsfb" 2041.55Suwe# elif NCOM > 0 2051.55Suwe# define CONSDEVNAME "com" 2061.55Suwe# else 2071.55Suwe# error CONSDEVNAME not defined and no known console device configured 2081.55Suwe# endif 2091.55Suwe#endif /* !CONSDEVNAME */ 2101.1Smatt 2111.1Smatt#ifndef CONCOMADDR 2121.1Smatt#define CONCOMADDR 0x3f8 2131.1Smatt#endif 2141.1Smatt 2151.55Suwe#ifndef CONSPEED 2161.55Suwe#define CONSPEED B115200 /* match NeTTrom */ 2171.1Smatt#endif 2181.1Smatt 2191.1Smatt#ifndef CONMODE 2201.1Smatt#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 2211.1Smatt#endif 2221.1Smatt 2231.1Smattint comcnspeed = CONSPEED; 2241.1Smattint comcnmode = CONMODE; 2251.1Smatt 2261.1Smattextern struct consdev kcomcons; 2271.1Smattstatic void kcomcnputc(dev_t, int); 2281.1Smatt 2291.55Suwe#if NIGSFB > 0 2301.55Suwe/* XXX: uwe */ 2311.55Suwe#define IGS_PCI_MEM_VBASE 0xfc000000 2321.55Suwe#define IGS_PCI_MEM_VSIZE 0x01000000 2331.55Suwe#define IGS_PCI_MEM_BASE 0x08000000 2341.55Suwe 2351.55Suweextern struct arm32_pci_chipset footbridge_pci_chipset; 2361.55Suweextern struct bus_space footbridge_pci_io_bs_tag; 2371.55Suweextern struct bus_space footbridge_pci_mem_bs_tag; 2381.55Suweextern void footbridge_pci_bs_tag_init(void); 2391.55Suwe 2401.55Suwe/* standard methods */ 2411.55Suweextern bs_map_proto(footbridge_mem); 2421.55Suweextern bs_unmap_proto(footbridge_mem); 2431.55Suwe 2441.55Suwe/* our hooks */ 2451.55Suwestatic bs_map_proto(nw_footbridge_mem); 2461.55Suwestatic bs_unmap_proto(nw_footbridge_mem); 2471.55Suwe#endif 2481.55Suwe 2491.55Suwe 2501.1Smatt/* 2511.1Smatt * void cpu_reboot(int howto, char *bootstr) 2521.1Smatt * 2531.1Smatt * Reboots the system 2541.1Smatt * 2551.1Smatt * Deal with any syncing, unmounting, dumping and shutdown hooks, 2561.1Smatt * then reset the CPU. 2571.1Smatt */ 2581.1Smatt 2591.1Smattvoid 2601.53Suwecpu_reboot(int howto, char *bootstr) 2611.1Smatt{ 2621.1Smatt#ifdef DIAGNOSTIC 2631.1Smatt /* info */ 2641.42Sthorpej printf("boot: howto=%08x curlwp=%p\n", howto, curlwp); 2651.1Smatt#endif 2661.1Smatt 2671.1Smatt /* 2681.1Smatt * If we are still cold then hit the air brakes 2691.1Smatt * and crash to earth fast 2701.1Smatt */ 2711.1Smatt if (cold) { 2721.1Smatt doshutdownhooks(); 2731.1Smatt printf("The operating system has halted.\n"); 2741.1Smatt printf("Please press any key to reboot.\n\n"); 2751.1Smatt cngetc(); 2761.1Smatt printf("rebooting...\n"); 2771.1Smatt cpu_reset(); 2781.1Smatt /*NOTREACHED*/ 2791.1Smatt } 2801.1Smatt 2811.1Smatt /* Disable console buffering */ 2821.1Smatt/* cnpollc(1);*/ 2831.1Smatt 2841.1Smatt /* 2851.1Smatt * If RB_NOSYNC was not specified sync the discs. 2861.53Suwe * Note: Unless cold is set to 1 here, syslogd will die during 2871.53Suwe * the unmount. It looks like syslogd is getting woken up 2881.53Suwe * only to find that it cannot page part of the binary in as 2891.53Suwe * the filesystem has been unmounted. 2901.1Smatt */ 2911.1Smatt if (!(howto & RB_NOSYNC)) 2921.1Smatt bootsync(); 2931.1Smatt 2941.1Smatt /* Say NO to interrupts */ 2951.1Smatt splhigh(); 2961.1Smatt 2971.1Smatt /* Do a dump if requested. */ 2981.1Smatt if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 2991.1Smatt dumpsys(); 3001.1Smatt 3011.1Smatt /* Run any shutdown hooks */ 3021.1Smatt doshutdownhooks(); 3031.1Smatt 3041.1Smatt /* Make sure IRQ's are disabled */ 3051.1Smatt IRQdisable; 3061.1Smatt 3071.1Smatt if (howto & RB_HALT) { 3081.1Smatt printf("The operating system has halted.\n"); 3091.1Smatt printf("Please press any key to reboot.\n\n"); 3101.1Smatt cngetc(); 3111.1Smatt } 3121.1Smatt 3131.1Smatt printf("rebooting...\n"); 3141.1Smatt cpu_reset(); 3151.1Smatt /*NOTREACHED*/ 3161.1Smatt} 3171.1Smatt 3181.52Suwe/* 3191.52Suwe * NB: this function runs with MMU disabled! 3201.52Suwe */ 3211.8Smattstatic void 3221.8Smattnetwinder_reset(void) 3231.8Smatt{ 3241.52Suwe register u_int base = DC21285_PCI_IO_BASE; 3251.52Suwe 3261.52Suwe#define PUTBYTE(reg, val) \ 3271.52Suwe *((volatile u_int8_t *)(base + (reg))) = (val) 3281.52Suwe 3291.52Suwe PUTBYTE(0x338, 0x84); /* Red led(GP17), fan on(GP12) */ 3301.52Suwe PUTBYTE(0x370, 0x87); /* Enter the extended function mode */ 3311.52Suwe PUTBYTE(0x370, 0x87); /* (need to write the magic twice) */ 3321.52Suwe PUTBYTE(0x370, 0x07); /* Select Logical Device Number reg */ 3331.52Suwe PUTBYTE(0x371, 0x07); /* Select Logical Device 7 (GPIO) */ 3341.52Suwe PUTBYTE(0x370, 0xe6); /* Select GP16 Control Reg */ 3351.52Suwe PUTBYTE(0x371, 0x00); /* Make GP16 an output */ 3361.52Suwe PUTBYTE(0x338, 0xc4); /* RESET(GP16), red led, fan on */ 3371.8Smatt} 3381.8Smatt 3391.1Smatt/* 3401.1Smatt * Mapping table for core kernel memory. This memory is mapped at init 3411.1Smatt * time with section mappings. 3421.1Smatt */ 3431.1Smattstruct l1_sec_map { 3441.1Smatt vm_offset_t va; 3451.1Smatt vm_offset_t pa; 3461.1Smatt vm_size_t size; 3471.16Sthorpej vm_prot_t prot; 3481.16Sthorpej int cache; 3491.1Smatt} l1_sec_table[] = { 3501.1Smatt /* Map 1MB for CSR space */ 3511.1Smatt { DC21285_ARMCSR_VBASE, DC21285_ARMCSR_BASE, 3521.16Sthorpej DC21285_ARMCSR_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3531.16Sthorpej PTE_NOCACHE }, 3541.16Sthorpej 3551.1Smatt /* Map 1MB for fast cache cleaning space */ 3561.4Schris { DC21285_CACHE_FLUSH_VBASE, DC21285_SA_CACHE_FLUSH_BASE, 3571.16Sthorpej DC21285_CACHE_FLUSH_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3581.16Sthorpej PTE_CACHE }, 3591.16Sthorpej 3601.1Smatt /* Map 1MB for PCI IO space */ 3611.1Smatt { DC21285_PCI_IO_VBASE, DC21285_PCI_IO_BASE, 3621.16Sthorpej DC21285_PCI_IO_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3631.16Sthorpej PTE_NOCACHE }, 3641.16Sthorpej 3651.1Smatt /* Map 1MB for PCI IACK space */ 3661.1Smatt { DC21285_PCI_IACK_VBASE, DC21285_PCI_IACK_SPECIAL, 3671.16Sthorpej DC21285_PCI_IACK_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3681.16Sthorpej PTE_NOCACHE }, 3691.16Sthorpej 3701.1Smatt /* Map 16MB of type 1 PCI config access */ 3711.1Smatt { DC21285_PCI_TYPE_1_CONFIG_VBASE, DC21285_PCI_TYPE_1_CONFIG, 3721.16Sthorpej DC21285_PCI_TYPE_1_CONFIG_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3731.16Sthorpej PTE_NOCACHE }, 3741.16Sthorpej 3751.1Smatt /* Map 16MB of type 0 PCI config access */ 3761.1Smatt { DC21285_PCI_TYPE_0_CONFIG_VBASE, DC21285_PCI_TYPE_0_CONFIG, 3771.16Sthorpej DC21285_PCI_TYPE_0_CONFIG_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3781.16Sthorpej PTE_NOCACHE }, 3791.16Sthorpej 3801.1Smatt /* Map 1MB of 32 bit PCI address space for ISA MEM accesses via PCI */ 3811.1Smatt { DC21285_PCI_ISA_MEM_VBASE, DC21285_PCI_MEM_BASE, 3821.16Sthorpej DC21285_PCI_ISA_MEM_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3831.16Sthorpej PTE_NOCACHE }, 3841.16Sthorpej 3851.55Suwe#if NIGSFB > 0 3861.55Suwe /* XXX: uwe: Map 16MB of PCI address space for CyberPro as console */ 3871.55Suwe { IGS_PCI_MEM_VBASE, DC21285_PCI_MEM_BASE + IGS_PCI_MEM_BASE, 3881.55Suwe IGS_PCI_MEM_VSIZE, VM_PROT_READ|VM_PROT_WRITE, 3891.55Suwe PTE_NOCACHE }, 3901.55Suwe#endif 3911.55Suwe 3921.16Sthorpej { 0, 0, 0, 0, 0 } 3931.1Smatt}; 3941.1Smatt 3951.1Smatt/* 3961.38Sthorpej * u_int initarm(...); 3971.1Smatt * 3981.1Smatt * Initial entry point on startup. This gets called before main() is 3991.1Smatt * entered. 4001.6Swiz * It should be responsible for setting up everything that must be 4011.1Smatt * in place when main is called. 4021.1Smatt * This includes 4031.1Smatt * Taking a copy of the boot configuration structure. 4041.1Smatt * Initialising the physical console so characters can be printed. 4051.1Smatt * Setting up page tables for the kernel 4061.1Smatt * Relocating the kernel to the bottom of physical memory 4071.1Smatt */ 4081.1Smatt 4091.1Smattu_int 4101.38Sthorpejinitarm(void *arg) 4111.1Smatt{ 4121.1Smatt int loop; 4131.1Smatt int loop1; 4141.1Smatt u_int l1pagetable; 4151.27Sthorpej extern char _end[]; 4161.1Smatt pv_addr_t kernel_l1pt; 4171.1Smatt 4181.27Sthorpej /* 4191.52Suwe * Turn the led off, then turn it yellow. 4201.52Suwe * 0x80 - red; 0x04 - fan; 0x02 - green. 4211.52Suwe */ 4221.52Suwe ISA_PUTBYTE(0x338, 0x04); 4231.52Suwe ISA_PUTBYTE(0x338, 0x86); 4241.52Suwe 4251.52Suwe /* 4261.27Sthorpej * Set up a diagnostic console so we can see what's going 4271.27Sthorpej * on. 4281.27Sthorpej */ 4291.1Smatt cn_tab = &kcomcons; 4301.27Sthorpej 4311.27Sthorpej /* Talk to the user */ 4321.27Sthorpej printf("\nNetBSD/netwinder booting ...\n"); 4331.27Sthorpej 4341.1Smatt /* 4351.1Smatt * Heads up ... Setup the CPU / MMU / TLB functions 4361.1Smatt */ 4371.1Smatt if (set_cpufuncs()) 4381.57Swiz panic("CPU not recognized!"); 4391.1Smatt 4401.27Sthorpej /* 4411.27Sthorpej * We are currently running with the MMU enabled and the 4421.27Sthorpej * entire address space mapped VA==PA, except for the 4431.27Sthorpej * first 64MB of RAM is also double-mapped at 0xf0000000. 4441.27Sthorpej * There is an L1 page table at 0x00008000. 4451.27Sthorpej * 4461.27Sthorpej * We also have the 21285's PCI I/O space mapped where 4471.27Sthorpej * we expect it. 4481.27Sthorpej */ 4491.27Sthorpej 4501.27Sthorpej printf("initarm: Configuring system ...\n"); 4511.27Sthorpej 4521.28Sthorpej /* 4531.28Sthorpej * Copy out the boot info passed by the firmware. Note that 4541.28Sthorpej * early versions of NeTTrom fill this in with bogus values, 4551.28Sthorpej * so we need to sanity check it. 4561.28Sthorpej */ 4571.28Sthorpej memcpy(&nwbootinfo, (caddr_t)(KERNEL_BASE + 0x100), 4581.28Sthorpej sizeof(nwbootinfo)); 4591.28Sthorpej#ifdef VERBOSE_INIT_ARM 4601.28Sthorpej printf("NeTTrom boot info:\n"); 4611.28Sthorpej printf("\tpage size = 0x%08lx\n", nwbootinfo.bi_pagesize); 4621.28Sthorpej printf("\tnpages = %ld (0x%08lx)\n", nwbootinfo.bi_nrpages, 4631.28Sthorpej nwbootinfo.bi_nrpages); 4641.28Sthorpej printf("\trootdev = 0x%08lx\n", nwbootinfo.bi_rootdev); 4651.28Sthorpej printf("\tcmdline = %s\n", nwbootinfo.bi_cmdline); 4661.28Sthorpej#endif 4671.28Sthorpej if (nwbootinfo.bi_nrpages != 0x02000 && 4681.28Sthorpej nwbootinfo.bi_nrpages != 0x04000 && 4691.28Sthorpej nwbootinfo.bi_nrpages != 0x08000 && 4701.28Sthorpej nwbootinfo.bi_nrpages != 0x10000) { 4711.28Sthorpej nwbootinfo.bi_pagesize = 0xdeadbeef; 4721.28Sthorpej nwbootinfo.bi_nrpages = 0x01000; /* 16MB */ 4731.28Sthorpej nwbootinfo.bi_rootdev = 0; 4741.28Sthorpej } 4751.28Sthorpej 4761.1Smatt /* Fake bootconfig structure for the benefit of pmap.c */ 4771.1Smatt /* XXX must make the memory description h/w independant */ 4781.1Smatt bootconfig.dramblocks = 1; 4791.1Smatt bootconfig.dram[0].address = 0; 4801.28Sthorpej bootconfig.dram[0].pages = nwbootinfo.bi_nrpages; 4811.1Smatt 4821.1Smatt /* 4831.27Sthorpej * Set up the variables that define the availablilty of 4841.27Sthorpej * physical memory. 4851.27Sthorpej * 4861.27Sthorpej * Since the NetWinder NeTTrom doesn't load ELF symbols 4871.27Sthorpej * for us, we can safely assume that everything after end[] 4881.27Sthorpej * is free. We start there and allocate upwards. 4891.1Smatt */ 4901.27Sthorpej physical_start = bootconfig.dram[0].address; 4911.44Sthorpej physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); 4921.1Smatt 4931.27Sthorpej physical_freestart = ((((vaddr_t) _end) + PGOFSET) & ~PGOFSET) - 4941.27Sthorpej KERNEL_BASE; 4951.27Sthorpej physical_freeend = physical_end; 4961.44Sthorpej free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; 4971.1Smatt 4981.27Sthorpej#ifdef VERBOSE_INIT_ARM 4991.27Sthorpej printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", 5001.27Sthorpej physical_freestart, free_pages, free_pages); 5011.1Smatt#endif 5021.1Smatt 5031.44Sthorpej physmem = (physical_end - physical_start) / PAGE_SIZE; 5041.1Smatt 5051.1Smatt /* Tell the user about the memory */ 5061.1Smatt printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, 5071.1Smatt physical_start, physical_end - 1); 5081.1Smatt 5091.1Smatt /* 5101.27Sthorpej * Okay, we need to allocate some fixed page tables to get the 5111.27Sthorpej * kernel going. We allocate one page directory and a number 5121.27Sthorpej * of page tables and store the physical addresses in the 5131.27Sthorpej * kernel_pt_table array. 5141.1Smatt * 5151.27Sthorpej * The kernel page directory must be on a 16K boundary. The page 5161.27Sthorpej * tables must be on 4K boundaries. What we do is allocate the 5171.27Sthorpej * page directory on the first 16K boundary that we encounter, 5181.27Sthorpej * and the page tables on 4K boundaries otherwise. Since we 5191.27Sthorpej * allocate at least 3 L2 page tables, we are guaranteed to 5201.27Sthorpej * encounter at least one 16K aligned region. 5211.1Smatt */ 5221.1Smatt 5231.1Smatt#ifdef VERBOSE_INIT_ARM 5241.1Smatt printf("Allocating page tables\n"); 5251.1Smatt#endif 5261.1Smatt 5271.1Smatt /* Define a macro to simplify memory allocation */ 5281.1Smatt#define valloc_pages(var, np) \ 5291.1Smatt alloc_pages((var).pv_pa, (np)); \ 5301.1Smatt (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; 5311.1Smatt 5321.1Smatt#define alloc_pages(var, np) \ 5331.1Smatt (var) = physical_freestart; \ 5341.44Sthorpej physical_freestart += ((np) * PAGE_SIZE);\ 5351.1Smatt free_pages -= (np); \ 5361.44Sthorpej memset((char *)(var), 0, ((np) * PAGE_SIZE)); 5371.1Smatt 5381.1Smatt loop1 = 0; 5391.1Smatt kernel_l1pt.pv_pa = 0; 5401.1Smatt for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { 5411.1Smatt /* Are we 16KB aligned for an L1 ? */ 5421.30Sthorpej if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0 5431.1Smatt && kernel_l1pt.pv_pa == 0) { 5441.44Sthorpej valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); 5451.1Smatt } else { 5461.45Sthorpej valloc_pages(kernel_pt_table[loop1], 5471.45Sthorpej L2_TABLE_SIZE / PAGE_SIZE); 5481.1Smatt ++loop1; 5491.1Smatt } 5501.1Smatt } 5511.1Smatt 5521.1Smatt /* This should never be able to happen but better confirm that. */ 5531.30Sthorpej if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) 5541.37Sprovos panic("initarm: Failed to align the kernel page directory"); 5551.1Smatt 5561.1Smatt /* 5571.1Smatt * Allocate a page for the system page mapped to V0x00000000 5581.1Smatt * This page will just contain the system vectors and can be 5591.1Smatt * shared by all processes. 5601.1Smatt */ 5611.1Smatt alloc_pages(systempage.pv_pa, 1); 5621.1Smatt 5631.1Smatt /* Allocate stacks for all modes */ 5641.1Smatt valloc_pages(irqstack, IRQ_STACK_SIZE); 5651.1Smatt valloc_pages(abtstack, ABT_STACK_SIZE); 5661.1Smatt valloc_pages(undstack, UND_STACK_SIZE); 5671.1Smatt valloc_pages(kernelstack, UPAGES); 5681.1Smatt 5691.1Smatt#ifdef VERBOSE_INIT_ARM 5701.27Sthorpej printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, 5711.27Sthorpej irqstack.pv_va); 5721.27Sthorpej printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, 5731.27Sthorpej abtstack.pv_va); 5741.27Sthorpej printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, 5751.27Sthorpej undstack.pv_va); 5761.27Sthorpej printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, 5771.27Sthorpej kernelstack.pv_va); 5781.1Smatt#endif 5791.1Smatt 5801.44Sthorpej alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); 5811.1Smatt 5821.1Smatt /* 5831.1Smatt * Ok we have allocated physical pages for the primary kernel 5841.1Smatt * page tables 5851.1Smatt */ 5861.1Smatt 5871.1Smatt#ifdef VERBOSE_INIT_ARM 5881.27Sthorpej printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); 5891.1Smatt#endif 5901.1Smatt 5911.1Smatt /* 5921.1Smatt * Now we start consturction of the L1 page table 5931.1Smatt * We start by mapping the L2 page tables into the L1. 5941.1Smatt * This means that we can replace L1 mappings later on if necessary 5951.1Smatt */ 5961.1Smatt l1pagetable = kernel_l1pt.pv_pa; 5971.1Smatt 5981.1Smatt /* Map the L2 pages tables in the L1 page table */ 5991.18Sthorpej pmap_link_l2pt(l1pagetable, 0x00000000, 6001.21Sthorpej &kernel_pt_table[KERNEL_PT_SYS]); 6011.18Sthorpej pmap_link_l2pt(l1pagetable, KERNEL_BASE, 6021.21Sthorpej &kernel_pt_table[KERNEL_PT_KERNEL]); 6031.1Smatt for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; ++loop) 6041.18Sthorpej pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, 6051.21Sthorpej &kernel_pt_table[KERNEL_PT_VMDATA + loop]); 6061.24Schris 6071.24Schris /* update the top of the kernel VM */ 6081.26Sthorpej pmap_curmaxkvaddr = 6091.26Sthorpej KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); 6101.1Smatt 6111.1Smatt#ifdef VERBOSE_INIT_ARM 6121.1Smatt printf("Mapping kernel\n"); 6131.1Smatt#endif 6141.1Smatt 6151.1Smatt /* Now we fill in the L2 pagetable for the kernel static code/data */ 6161.27Sthorpej { 6171.27Sthorpej /* 6181.27Sthorpej * The kernel starts in the first 1MB of RAM, and we'd 6191.27Sthorpej * like to use a section mapping for text, so we'll just 6201.27Sthorpej * map from KERNEL_BASE to etext[] to _end[]. 6211.27Sthorpej */ 6221.1Smatt 6231.27Sthorpej extern char etext[]; 6241.27Sthorpej size_t textsize = (uintptr_t) etext - KERNEL_BASE; 6251.27Sthorpej size_t totalsize = (uintptr_t) _end - KERNEL_BASE; 6261.2Smatt u_int logical; 6271.7Smatt 6281.27Sthorpej textsize = (textsize + PGOFSET) & ~PGOFSET; 6291.27Sthorpej totalsize = (totalsize + PGOFSET) & ~PGOFSET; 6301.27Sthorpej 6311.7Smatt textsize = textsize & ~PGOFSET; 6321.7Smatt totalsize = (totalsize + PGOFSET) & ~PGOFSET; 6331.27Sthorpej 6341.27Sthorpej logical = 0; /* offset into RAM */ 6351.27Sthorpej 6361.27Sthorpej logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 6371.27Sthorpej physical_start + logical, textsize, 6381.19Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6391.27Sthorpej logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 6401.27Sthorpej physical_start + logical, totalsize - textsize, 6411.19Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6421.7Smatt } 6431.1Smatt 6441.1Smatt#ifdef VERBOSE_INIT_ARM 6451.1Smatt printf("Constructing L2 page tables\n"); 6461.1Smatt#endif 6471.1Smatt 6481.1Smatt /* Map the stack pages */ 6491.21Sthorpej pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, 6501.44Sthorpej IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6511.21Sthorpej pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, 6521.44Sthorpej ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6531.21Sthorpej pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, 6541.44Sthorpej UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6551.21Sthorpej pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, 6561.44Sthorpej UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6571.19Sthorpej 6581.45Sthorpej pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, 6591.45Sthorpej L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 6601.45Sthorpej 6611.45Sthorpej for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { 6621.45Sthorpej pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, 6631.45Sthorpej kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, 6641.45Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 6651.45Sthorpej } 6661.1Smatt 6671.29Sthorpej /* Map the vector page. */ 6681.29Sthorpej pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, 6691.17Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6701.1Smatt 6711.27Sthorpej /* 6721.27Sthorpej * Map devices we can map w/ section mappings. 6731.27Sthorpej */ 6741.1Smatt loop = 0; 6751.1Smatt while (l1_sec_table[loop].size) { 6761.1Smatt vm_size_t sz; 6771.1Smatt 6781.1Smatt#ifdef VERBOSE_INIT_ARM 6791.1Smatt printf("%08lx -> %08lx @ %08lx\n", l1_sec_table[loop].pa, 6801.1Smatt l1_sec_table[loop].pa + l1_sec_table[loop].size - 1, 6811.1Smatt l1_sec_table[loop].va); 6821.1Smatt#endif 6831.30Sthorpej for (sz = 0; sz < l1_sec_table[loop].size; sz += L1_S_SIZE) 6841.16Sthorpej pmap_map_section(l1pagetable, 6851.16Sthorpej l1_sec_table[loop].va + sz, 6861.1Smatt l1_sec_table[loop].pa + sz, 6871.16Sthorpej l1_sec_table[loop].prot, 6881.16Sthorpej l1_sec_table[loop].cache); 6891.1Smatt ++loop; 6901.1Smatt } 6911.1Smatt 6921.1Smatt /* 6931.1Smatt * Now we have the real page tables in place so we can switch to them. 6941.27Sthorpej * Once this is done we will be running with the REAL kernel page 6951.27Sthorpej * tables. 6961.1Smatt */ 6971.1Smatt 6981.1Smatt /* Switch tables */ 6991.1Smatt#ifdef VERBOSE_INIT_ARM 7001.27Sthorpej printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", 7011.1Smatt physical_freestart, free_pages, free_pages); 7021.1Smatt printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); 7031.1Smatt#endif 7041.1Smatt 7051.45Sthorpej cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 7061.1Smatt setttb(kernel_l1pt.pv_pa); 7071.45Sthorpej cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); 7081.45Sthorpej 7091.45Sthorpej /* 7101.45Sthorpej * Moved from cpu_startup() as data_abort_handler() references 7111.45Sthorpej * this during uvm init 7121.45Sthorpej */ 7131.45Sthorpej proc0paddr = (struct user *)kernelstack.pv_va; 7141.45Sthorpej lwp0.l_addr = proc0paddr; 7151.1Smatt 7161.1Smatt#ifdef VERBOSE_INIT_ARM 7171.1Smatt printf("done!\n"); 7181.1Smatt#endif 7191.1Smatt 7201.1Smatt /* 7211.1Smatt * XXX this should only be done in main() but it useful to 7221.1Smatt * have output earlier ... 7231.1Smatt */ 7241.1Smatt consinit(); 7251.1Smatt 7261.1Smatt#ifdef VERBOSE_INIT_ARM 7271.1Smatt printf("bootstrap done.\n"); 7281.1Smatt#endif 7291.1Smatt 7301.29Sthorpej arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); 7311.1Smatt 7321.1Smatt /* 7331.1Smatt * Pages were allocated during the secondary bootstrap for the 7341.1Smatt * stacks for different CPU modes. 7351.1Smatt * We must now set the r13 registers in the different CPU modes to 7361.1Smatt * point to these stacks. 7371.1Smatt * Since the ARM stacks use STMFD etc. we must set r13 to the top end 7381.1Smatt * of the stack memory. 7391.1Smatt */ 7401.1Smatt printf("init subsystems: stacks "); 7411.1Smatt 7421.44Sthorpej set_stackptr(PSR_IRQ32_MODE, 7431.44Sthorpej irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); 7441.44Sthorpej set_stackptr(PSR_ABT32_MODE, 7451.44Sthorpej abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); 7461.44Sthorpej set_stackptr(PSR_UND32_MODE, 7471.44Sthorpej undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); 7481.1Smatt 7491.1Smatt /* 7501.1Smatt * Well we should set a data abort handler. 7511.27Sthorpej * Once things get going this will change as we will need a proper 7521.27Sthorpej * handler. 7531.1Smatt * Until then we will use a handler that just panics but tells us 7541.1Smatt * why. 7551.1Smatt * Initialisation of the vectors will just panic on a data abort. 7561.58Sabs * This just fills in a slightly better one. 7571.1Smatt */ 7581.1Smatt printf("vectors "); 7591.1Smatt data_abort_handler_address = (u_int)data_abort_handler; 7601.1Smatt prefetch_abort_handler_address = (u_int)prefetch_abort_handler; 7611.1Smatt undefined_handler_address = (u_int)undefinedinstruction_bounce; 7621.1Smatt 7631.1Smatt /* Initialise the undefined instruction handlers */ 7641.1Smatt printf("undefined "); 7651.1Smatt undefined_init(); 7661.1Smatt 7671.33Sthorpej /* Load memory into UVM. */ 7681.33Sthorpej printf("page "); 7691.33Sthorpej uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ 7701.33Sthorpej 7711.33Sthorpej /* XXX Always one RAM block -- nuke the loop. */ 7721.33Sthorpej for (loop = 0; loop < bootconfig.dramblocks; loop++) { 7731.33Sthorpej paddr_t start = (paddr_t)bootconfig.dram[loop].address; 7741.44Sthorpej paddr_t end = start + (bootconfig.dram[loop].pages * PAGE_SIZE); 7751.33Sthorpej#if NISADMA > 0 7761.33Sthorpej paddr_t istart, isize; 7771.34Sthorpej extern struct arm32_dma_range *footbridge_isa_dma_ranges; 7781.34Sthorpej extern int footbridge_isa_dma_nranges; 7791.33Sthorpej#endif 7801.33Sthorpej 7811.33Sthorpej if (start < physical_freestart) 7821.33Sthorpej start = physical_freestart; 7831.33Sthorpej if (end > physical_freeend) 7841.33Sthorpej end = physical_freeend; 7851.33Sthorpej 7861.33Sthorpej#if 0 7871.33Sthorpej printf("%d: %lx -> %lx\n", loop, start, end - 1); 7881.33Sthorpej#endif 7891.33Sthorpej 7901.33Sthorpej#if NISADMA > 0 7911.34Sthorpej if (arm32_dma_range_intersect(footbridge_isa_dma_ranges, 7921.34Sthorpej footbridge_isa_dma_nranges, 7931.34Sthorpej start, end - start, 7941.34Sthorpej &istart, &isize)) { 7951.33Sthorpej /* 7961.33Sthorpej * Place the pages that intersect with the 7971.33Sthorpej * ISA DMA range onto the ISA DMA free list. 7981.33Sthorpej */ 7991.33Sthorpej#if 0 8001.33Sthorpej printf(" ISADMA 0x%lx -> 0x%lx\n", istart, 8011.33Sthorpej istart + isize - 1); 8021.33Sthorpej#endif 8031.33Sthorpej uvm_page_physload(atop(istart), 8041.33Sthorpej atop(istart + isize), atop(istart), 8051.33Sthorpej atop(istart + isize), VM_FREELIST_ISADMA); 8061.33Sthorpej 8071.33Sthorpej /* 8081.33Sthorpej * Load the pieces that come before the 8091.33Sthorpej * intersection onto the default free list. 8101.33Sthorpej */ 8111.33Sthorpej if (start < istart) { 8121.33Sthorpej#if 0 8131.33Sthorpej printf(" BEFORE 0x%lx -> 0x%lx\n", 8141.33Sthorpej start, istart - 1); 8151.33Sthorpej#endif 8161.33Sthorpej uvm_page_physload(atop(start), 8171.33Sthorpej atop(istart), atop(start), 8181.33Sthorpej atop(istart), VM_FREELIST_DEFAULT); 8191.33Sthorpej } 8201.33Sthorpej 8211.33Sthorpej /* 8221.33Sthorpej * Load the pieces that come after the 8231.33Sthorpej * intersection onto the default free list. 8241.33Sthorpej */ 8251.33Sthorpej if ((istart + isize) < end) { 8261.33Sthorpej#if 0 8271.33Sthorpej printf(" AFTER 0x%lx -> 0x%lx\n", 8281.33Sthorpej (istart + isize), end - 1); 8291.33Sthorpej#endif 8301.33Sthorpej uvm_page_physload(atop(istart + isize), 8311.33Sthorpej atop(end), atop(istart + isize), 8321.33Sthorpej atop(end), VM_FREELIST_DEFAULT); 8331.33Sthorpej } 8341.33Sthorpej } else { 8351.33Sthorpej uvm_page_physload(atop(start), atop(end), 8361.33Sthorpej atop(start), atop(end), VM_FREELIST_DEFAULT); 8371.33Sthorpej } 8381.33Sthorpej#else /* NISADMA > 0 */ 8391.33Sthorpej uvm_page_physload(atop(start), atop(end), 8401.33Sthorpej atop(start), atop(end), VM_FREELIST_DEFAULT); 8411.33Sthorpej#endif /* NISADMA > 0 */ 8421.33Sthorpej } 8431.33Sthorpej 8441.1Smatt /* Boot strap pmap telling it where the kernel page table is */ 8451.1Smatt printf("pmap "); 8461.49Sthorpej pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE, 8471.49Sthorpej KERNEL_VM_BASE + KERNEL_VM_SIZE); 8481.1Smatt 8491.52Suwe /* Now that pmap is inited, we can set cpu_reset_address */ 8501.52Suwe cpu_reset_address = (u_int)vtophys((vaddr_t)netwinder_reset); 8511.52Suwe 8521.1Smatt /* Setup the IRQ system */ 8531.1Smatt printf("irq "); 8541.41Schris footbridge_intr_init(); 8551.1Smatt printf("done.\n"); 8561.28Sthorpej 8571.28Sthorpej /* 8581.28Sthorpej * Warn the user if the bootinfo was bogus. We already 8591.28Sthorpej * faked up some safe values. 8601.28Sthorpej */ 8611.28Sthorpej if (nwbootinfo.bi_pagesize == 0xdeadbeef) 8621.28Sthorpej printf("WARNING: NeTTrom boot info corrupt\n"); 8631.1Smatt 8641.1Smatt#ifdef IPKDB 8651.1Smatt /* Initialise ipkdb */ 8661.1Smatt ipkdb_init(); 8671.1Smatt if (boothowto & RB_KDB) 8681.1Smatt ipkdb_connect(0); 8691.1Smatt#endif 8701.1Smatt 8711.12Sthorpej 8721.46Sragge#if NKSYMS || defined(DDB) || defined(LKM) 8731.12Sthorpej /* Firmware doesn't load symbols. */ 8741.46Sragge ksyms_init(0, NULL, NULL); 8751.46Sragge#endif 8761.1Smatt 8771.46Sragge#ifdef DDB 8781.46Sragge db_machine_init(); 8791.1Smatt if (boothowto & RB_KDB) 8801.1Smatt Debugger(); 8811.1Smatt#endif 8821.52Suwe 8831.52Suwe /* Turn the led green */ 8841.52Suwe ISA_PUTBYTE(0x338, 0x06); 8851.1Smatt 8861.1Smatt /* We return the new stack pointer address */ 8871.1Smatt return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); 8881.1Smatt} 8891.1Smatt 8901.1Smattvoid 8911.53Suweprocess_kernel_args(char *args) 8921.1Smatt{ 8931.1Smatt 8941.1Smatt boothowto = 0; 8951.1Smatt 8961.1Smatt /* Make a local copy of the bootargs */ 8971.1Smatt strncpy(bootargs, args, MAX_BOOT_STRING); 8981.1Smatt 8991.1Smatt args = bootargs; 9001.1Smatt boot_file = bootargs; 9011.1Smatt 9021.1Smatt /* Skip the kernel image filename */ 9031.1Smatt while (*args != ' ' && *args != 0) 9041.1Smatt ++args; 9051.1Smatt 9061.1Smatt if (*args != 0) 9071.1Smatt *args++ = 0; 9081.1Smatt 9091.1Smatt while (*args == ' ') 9101.1Smatt ++args; 9111.1Smatt 9121.1Smatt boot_args = args; 9131.1Smatt 9141.1Smatt printf("bootfile: %s\n", boot_file); 9151.1Smatt printf("bootargs: %s\n", boot_args); 9161.1Smatt 9171.1Smatt parse_mi_bootargs(boot_args); 9181.1Smatt} 9191.1Smatt 9201.1Smattvoid 9211.1Smattconsinit(void) 9221.1Smatt{ 9231.1Smatt static int consinit_called = 0; 9241.59She const char *console = CONSDEVNAME; 9251.1Smatt 9261.1Smatt if (consinit_called != 0) 9271.1Smatt return; 9281.1Smatt 9291.1Smatt consinit_called = 1; 9301.1Smatt 9311.55Suwe#ifdef DIAGNOSTIC 9321.55Suwe printf("consinit(\"%s\")\n", console); 9331.55Suwe#endif 9341.55Suwe 9351.1Smatt#if NISA > 0 9361.1Smatt /* Initialise the ISA subsystem early ... */ 9371.40Schris isa_footbridge_init(DC21285_PCI_IO_VBASE, DC21285_PCI_ISA_MEM_VBASE); 9381.1Smatt#endif 9391.1Smatt 9401.55Suwe if (strncmp(console, "igsfb", 5) == 0) { 9411.55Suwe#if NIGSFB > 0 9421.55Suwe int res; 9431.55Suwe 9441.55Suwe footbridge_pci_bs_tag_init(); 9451.1Smatt 9461.55Suwe /* 9471.55Suwe * XXX: uwe: special case mapping for the igsfb memory space. 9481.55Suwe * 9491.55Suwe * The problem with this is that when footbridge is 9501.55Suwe * attached during normal autoconfiguration the bus 9511.55Suwe * space tags will be reinited and these hooks lost. 9521.55Suwe * However, since igsfb(4) don't unmap memory during 9531.55Suwe * normal operation, this is ok. But if the igsfb is 9541.55Suwe * configured but is not a console, we waste 16M of 9551.55Suwe * kernel VA space. 9561.55Suwe */ 9571.55Suwe footbridge_pci_mem_bs_tag.bs_map = nw_footbridge_mem_bs_map; 9581.55Suwe footbridge_pci_mem_bs_tag.bs_unmap = nw_footbridge_mem_bs_unmap; 9591.55Suwe 9601.55Suwe igsfb_pci_cnattach(&footbridge_pci_io_bs_tag, 9611.55Suwe &footbridge_pci_mem_bs_tag, 9621.55Suwe &footbridge_pci_chipset, 9631.55Suwe 0, 8, 0); 9641.55Suwe#if NPCKBC > 0 9651.55Suwe res = pckbc_cnattach(&isa_io_bs_tag, 9661.55Suwe IO_KBD, KBCMDP, PCKBC_KBD_SLOT); 9671.55Suwe if (res) 9681.55Suwe printf("pckbc_cnattach: %d!\n", res); 9691.55Suwe#endif 9701.1Smatt#else 9711.55Suwe panic("igsfb console not configured"); 9721.55Suwe#endif /* NIGSFB */ 9731.1Smatt } else { 9741.55Suwe#ifdef DIAGNOSTIC 9751.55Suwe if (strncmp(console, "com", 3) != 0) { 9761.55Suwe printf("consinit: unknown CONSDEVNAME=\"%s\"," 9771.55Suwe " falling back to \"com\"\n", console); 9781.55Suwe } 9791.55Suwe#endif 9801.55Suwe#if NCOM > 0 9811.1Smatt if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed, 9821.55Suwe COM_FREQ, COM_TYPE_NORMAL, comcnmode)) 9831.1Smatt panic("can't init serial console @%x", CONCOMADDR); 9841.1Smatt#else 9851.55Suwe panic("serial console @%x not configured", CONCOMADDR); 9861.55Suwe#endif 9871.55Suwe } 9881.55Suwe} 9891.55Suwe 9901.55Suwe 9911.55Suwe#if NIGSFB > 0 9921.55Suwestatic int 9931.55Suwenw_footbridge_mem_bs_map(t, bpa, size, cacheable, bshp) 9941.55Suwe void *t; 9951.55Suwe bus_addr_t bpa; 9961.55Suwe bus_size_t size; 9971.55Suwe int cacheable; 9981.55Suwe bus_space_handle_t *bshp; 9991.55Suwe{ 10001.55Suwe bus_addr_t startpa, endpa; 10011.55Suwe 10021.55Suwe /* Round the allocation to page boundries */ 10031.55Suwe startpa = trunc_page(bpa); 10041.55Suwe endpa = round_page(bpa + size); 10051.55Suwe 10061.55Suwe /* 10071.55Suwe * Check for mappings of the igsfb(4) memory space as we have 10081.55Suwe * this space already mapped. 10091.55Suwe */ 10101.55Suwe if (startpa >= IGS_PCI_MEM_BASE 10111.55Suwe && endpa < (IGS_PCI_MEM_BASE + IGS_PCI_MEM_VSIZE)) { 10121.55Suwe /* Store the bus space handle */ 10131.55Suwe *bshp = IGS_PCI_MEM_VBASE 10141.55Suwe + (bpa - IGS_PCI_MEM_BASE); 10151.55Suwe#ifdef DEBUG 10161.55Suwe printf("nw/mem_bs_map: %08x+%08x: %08x..%08x -> %08x\n", 10171.55Suwe (u_int32_t)bpa, (u_int32_t)size, 10181.55Suwe (u_int32_t)startpa, (u_int32_t)endpa, 10191.55Suwe (u_int32_t)*bshp); 10201.1Smatt#endif 10211.55Suwe return 0; 10221.1Smatt } 10231.55Suwe 10241.55Suwe return (footbridge_mem_bs_map(t, bpa, size, cacheable, bshp)); 10251.1Smatt} 10261.55Suwe 10271.55Suwe 10281.55Suwestatic void 10291.55Suwenw_footbridge_mem_bs_unmap(t, bsh, size) 10301.55Suwe void *t; 10311.55Suwe bus_space_handle_t bsh; 10321.55Suwe bus_size_t size; 10331.55Suwe{ 10341.55Suwe 10351.55Suwe /* 10361.55Suwe * Check for mappings of the igsfb(4) memory space as we have 10371.55Suwe * this space already mapped. 10381.55Suwe */ 10391.55Suwe if (bsh >= IGS_PCI_MEM_VBASE 10401.55Suwe && bsh < (IGS_PCI_MEM_VBASE + IGS_PCI_MEM_VSIZE)) { 10411.55Suwe#ifdef DEBUG 10421.55Suwe printf("nw/bs_unmap: 0x%08x\n", (u_int32_t)bsh); 10431.55Suwe#endif 10441.55Suwe return; 10451.55Suwe } 10461.55Suwe 10471.55Suwe footbridge_mem_bs_unmap(t, bsh, size); 10481.55Suwe} 10491.55Suwe#endif /* NIGSFB */ 10501.55Suwe 10511.1Smatt 10521.1Smattstatic bus_space_handle_t kcom_base = (bus_space_handle_t) (DC21285_PCI_IO_VBASE + CONCOMADDR); 10531.1Smatt 10541.31Sthorpej#define KCOM_GETBYTE(r) generic_bs_r_1(0, kcom_base, (r)) 10551.31Sthorpej#define KCOM_PUTBYTE(r,v) generic_bs_w_1(0, kcom_base, (r), (v)) 10561.1Smatt 10571.1Smattstatic int 10581.1Smattkcomcngetc(dev_t dev) 10591.1Smatt{ 10601.1Smatt int stat, c; 10611.1Smatt 10621.1Smatt /* block until a character becomes available */ 10631.1Smatt while (!ISSET(stat = KCOM_GETBYTE(com_lsr), LSR_RXRDY)) 10641.1Smatt ; 10651.1Smatt 10661.1Smatt c = KCOM_GETBYTE(com_data); 10671.1Smatt stat = KCOM_GETBYTE(com_iir); 10681.1Smatt return c; 10691.1Smatt} 10701.1Smatt 10711.1Smatt/* 10721.1Smatt * Console kernel output character routine. 10731.1Smatt */ 10741.1Smattstatic void 10751.1Smattkcomcnputc(dev_t dev, int c) 10761.1Smatt{ 10771.1Smatt int timo; 10781.1Smatt 10791.1Smatt /* wait for any pending transmission to finish */ 10801.1Smatt timo = 150000; 10811.1Smatt while (!ISSET(KCOM_GETBYTE(com_lsr), LSR_TXRDY) && --timo) 10821.1Smatt continue; 10831.1Smatt 10841.1Smatt KCOM_PUTBYTE(com_data, c); 10851.1Smatt 10861.1Smatt /* wait for this transmission to complete */ 10871.1Smatt timo = 1500000; 10881.1Smatt while (!ISSET(KCOM_GETBYTE(com_lsr), LSR_TXRDY) && --timo) 10891.1Smatt continue; 10901.1Smatt} 10911.1Smatt 10921.1Smattstatic void 10931.1Smattkcomcnpollc(dev_t dev, int on) 10941.1Smatt{ 10951.1Smatt} 10961.1Smatt 10971.1Smattstruct consdev kcomcons = { 10981.1Smatt NULL, NULL, kcomcngetc, kcomcnputc, kcomcnpollc, NULL, 10991.43She NULL, NULL, NODEV, CN_NORMAL 11001.1Smatt}; 1101