31e40c8ce1
MIPS32 4Kc CPU board, with support for the MIPS64 5Kc and the QED RM5261 CPU boards to follow. The cs4281 audio hasn't been tested, there are some interrupt problems with onboard the pciide, but all other on-board peripherals work. The evbmips port will support more MIPS evaluation boards in the future.
505 lines
13 KiB
C
505 lines
13 KiB
C
/* $NetBSD: machdep.c,v 1.1 2002/03/07 14:44:04 simonb Exp $ */
|
|
|
|
/*
|
|
* Copyright 2001, 2002 Wasabi Systems, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Written by Jason R. Thorpe and Simon Burge for Wasabi Systems, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed for the NetBSD Project by
|
|
* Wasabi Systems, Inc.
|
|
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
|
* or promote products derived from this software without specific prior
|
|
* written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1988 University of Utah.
|
|
* Copyright (c) 1992, 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* the Systems Programming Group of the University of Utah Computer
|
|
* Science Department, The Mach Operating System project at
|
|
* Carnegie-Mellon University and Ralph Campbell.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* @(#)machdep.c 8.3 (Berkeley) 1/12/94
|
|
* from: Utah Hdr: machdep.c 1.63 91/04/24
|
|
*/
|
|
|
|
#include "opt_ddb.h"
|
|
#include "opt_execfmt.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/user.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/kcore.h>
|
|
#include <sys/boot_flag.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/termios.h>
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
#include <dev/cons.h>
|
|
|
|
#ifdef DDB
|
|
#include <machine/db_machdep.h>
|
|
#include <ddb/db_extern.h>
|
|
#endif
|
|
|
|
#include <machine/cpu.h>
|
|
#include <machine/psl.h>
|
|
#include <machine/yamon.h>
|
|
|
|
#include <evbmips/malta/autoconf.h>
|
|
#include <evbmips/malta/maltareg.h>
|
|
#include <evbmips/malta/maltavar.h>
|
|
|
|
#include "com.h"
|
|
#if NCOM > 0
|
|
#include <dev/ic/comreg.h>
|
|
#include <dev/ic/comvar.h>
|
|
|
|
int comcnrate = 38400; /* XXX should be config option */
|
|
#endif /* NCOM > 0 */
|
|
|
|
|
|
#define REGVAL(x) *((__volatile u_int32_t *)(MIPS_PHYS_TO_KSEG1((x))))
|
|
|
|
struct malta_config malta_configuration;
|
|
|
|
/* For sysctl. */
|
|
char machine[] = MACHINE;
|
|
char machine_arch[] = MACHINE_ARCH;
|
|
char cpu_model[] = "MIPS Malta Evaluation Board";
|
|
|
|
/* Our exported CPU info; we can have only one. */
|
|
struct cpu_info cpu_info_store;
|
|
|
|
/* Maps for VM objects. */
|
|
struct vm_map *exec_map = NULL;
|
|
struct vm_map *mb_map = NULL;
|
|
struct vm_map *phys_map = NULL;
|
|
|
|
int physmem; /* Total physical memory */
|
|
|
|
int netboot; /* Are we netbooting? */
|
|
|
|
int cpuspeed;
|
|
|
|
yamon_env_var *yamon_envp;
|
|
|
|
phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
|
|
int mem_cluster_cnt;
|
|
|
|
void configure(void);
|
|
void mach_init(int, char **, yamon_env_var *, u_long);
|
|
|
|
/*
|
|
* safepri is a safe priority for sleep to set for a spin-wait during
|
|
* autoconfiguration or after a panic. Used as an argument to splx().
|
|
*/
|
|
int safepri = MIPS1_PSL_LOWIPL;
|
|
|
|
extern struct user *proc0paddr;
|
|
|
|
/*
|
|
* Do all the stuff that locore normally does before calling main().
|
|
*/
|
|
void
|
|
mach_init(int argc, char **argv, yamon_env_var *envp, u_long memsize)
|
|
{
|
|
struct malta_config *mcp = &malta_configuration;
|
|
bus_space_handle_t sh;
|
|
caddr_t kernend, v;
|
|
u_long first, last;
|
|
vsize_t size;
|
|
char *cp;
|
|
int i, howto;
|
|
uint8_t *brkres = (uint8_t *)MIPS_PHYS_TO_KSEG1(MALTA_BRKRES);
|
|
|
|
extern char edata[], end[];
|
|
|
|
*brkres = 0; /* Disable BREAK==reset on console */
|
|
|
|
/* Get the propaganda in early! */
|
|
led_display_str("NetBSD");
|
|
|
|
/*
|
|
* Clear the BSS segment.
|
|
*/
|
|
kernend = (caddr_t)mips_round_page(end);
|
|
memset(edata, 0, kernend - edata);
|
|
|
|
/* save the yamon environment pointer */
|
|
yamon_envp = envp;
|
|
|
|
/* Use YAMON callbacks for early console I/O */
|
|
cn_tab = &yamon_promcd;
|
|
|
|
uvm_setpagesize();
|
|
|
|
physmem = btoc(memsize);
|
|
|
|
gt_pci_init(&mcp->mc_pc, &mcp->mc_gt);
|
|
malta_bus_io_init(&mcp->mc_iot, mcp);
|
|
malta_bus_mem_init(&mcp->mc_memt, mcp);
|
|
malta_dma_init(mcp);
|
|
|
|
#if 1
|
|
#if NCOM > 0
|
|
/*
|
|
* Delay to allow firmware putchars to complete.
|
|
* FIFO depth * character time.
|
|
* character time = (1000000 / (defaultrate / 10))
|
|
*/
|
|
DELAY(160000000 / comcnrate);
|
|
if (comcnattach(&mcp->mc_iot, 0x3f8, comcnrate,
|
|
COM_FREQ,
|
|
(TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
|
|
panic("malta: unable to initialize serial console");
|
|
#else
|
|
panic("malta: not configured to use serial console");
|
|
#endif /* NCOM > 0 */
|
|
#endif
|
|
|
|
bus_space_map(&mcp->mc_iot, MALTA_RTCADR, 2, 0, &sh);
|
|
malta_cal_timer(&mcp->mc_iot, sh);
|
|
bus_space_unmap(&mcp->mc_iot, sh, 2);
|
|
|
|
consinit();
|
|
|
|
/*
|
|
* Copy exception-dispatch code down to exception vector.
|
|
* Initialize locore-function vector.
|
|
* Clear out the I and D caches.
|
|
*/
|
|
mips_vector_init();
|
|
|
|
mem_clusters[0].start = 0;
|
|
mem_clusters[0].size = ctob(physmem);
|
|
mem_cluster_cnt = 1;
|
|
|
|
/*
|
|
* XXX: check argv[0] - do something if "gdb"???
|
|
*/
|
|
|
|
/*
|
|
* Look at arguments passed to us and compute boothowto.
|
|
*/
|
|
boothowto = RB_AUTOBOOT;
|
|
for (i = 1; i < argc; i++) {
|
|
for (cp = argv[i]; *cp; cp++) {
|
|
/* Ignore superfluous '-', if there is one */
|
|
if (*cp == '-')
|
|
continue;
|
|
|
|
howto = 0;
|
|
BOOT_FLAG(*cp, howto);
|
|
if (! howto)
|
|
printf("bootflag '%c' not recognised\n", *cp);
|
|
else
|
|
boothowto |= howto;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Load the rest of the available pages into the VM system.
|
|
*/
|
|
first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
|
|
last = mem_clusters[0].start + mem_clusters[0].size;
|
|
uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
|
|
VM_FREELIST_DEFAULT);
|
|
|
|
/*
|
|
* Initialize error message buffer (at end of core).
|
|
*/
|
|
mips_init_msgbuf();
|
|
|
|
/*
|
|
* Compute the size of system data structures. pmap_bootstrap()
|
|
* needs some of this information.
|
|
*/
|
|
size = (vsize_t)allocsys(NULL, NULL);
|
|
|
|
pmap_bootstrap();
|
|
|
|
/*
|
|
* Allocate space for proc0's USPACE.
|
|
*/
|
|
v = (caddr_t)uvm_pageboot_alloc(USPACE);
|
|
proc0.p_addr = proc0paddr = (struct user *)v;
|
|
proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1;
|
|
curpcb = &proc0.p_addr->u_pcb;
|
|
curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */
|
|
|
|
/*
|
|
* Allocate space for system data structures. These data structures
|
|
* are allocated here instead of cpu_startup() because physical
|
|
* memory is directly addressable. We don't have to map these into
|
|
* virtual address space.
|
|
*/
|
|
v = (caddr_t)uvm_pageboot_alloc(size);
|
|
if ((allocsys(v, NULL) - v) != size)
|
|
panic("mach_init: table size inconsistency");
|
|
|
|
/*
|
|
* Initialize debuggers, and break into them, if appropriate.
|
|
*/
|
|
#ifdef DDB
|
|
ddb_init(0, 0, 0);
|
|
#endif
|
|
|
|
if (boothowto & RB_KDB)
|
|
#if defined(DDB)
|
|
Debugger();
|
|
#endif
|
|
}
|
|
|
|
void
|
|
consinit(void)
|
|
{
|
|
|
|
/*
|
|
* Everything related to console initialization is done
|
|
* in mach_init().
|
|
*/
|
|
}
|
|
|
|
/*
|
|
* Allocate memory for variable-sized tables,
|
|
*/
|
|
void
|
|
cpu_startup()
|
|
{
|
|
unsigned i;
|
|
int base, residual;
|
|
vaddr_t minaddr, maxaddr;
|
|
vsize_t size;
|
|
char pbuf[9];
|
|
|
|
/*
|
|
* Good {morning,afternoon,evening,night}.
|
|
*/
|
|
printf(version);
|
|
format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
|
|
printf("%s memory", pbuf);
|
|
|
|
/*
|
|
* Virtual memory is bootstrapped -- notify the bus spaces
|
|
* that memory allocation is now safe.
|
|
*/
|
|
malta_configuration.mc_mallocsafe = 1;
|
|
|
|
/*
|
|
* Allocate virtual address space for file I/O buffers.
|
|
* Note they are different than the array of headers, 'buf',
|
|
* and usually occupy more virtual memory than physical.
|
|
*/
|
|
size = MAXBSIZE * nbuf;
|
|
if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size),
|
|
NULL, UVM_UNKNOWN_OFFSET, 0,
|
|
UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
|
|
UVM_ADV_NORMAL, 0)) != 0)
|
|
panic("startup: cannot allocate VM for buffers");
|
|
minaddr = (vaddr_t)buffers;
|
|
base = bufpages / nbuf;
|
|
residual = bufpages % nbuf;
|
|
for (i = 0; i < nbuf; i++) {
|
|
vsize_t curbufsize;
|
|
vaddr_t curbuf;
|
|
struct vm_page *pg;
|
|
|
|
/*
|
|
* Each buffer has MAXBSIZE bytes of VM space allocated. Of
|
|
* that MAXBSIZE space, we allocate and map (base+1) pages
|
|
* for the first "residual" buffers, and then we allocate
|
|
* "base" pages for the rest.
|
|
*/
|
|
curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
|
|
curbufsize = NBPG * ((i < residual) ? (base + 1) : base);
|
|
|
|
while (curbufsize) {
|
|
pg = uvm_pagealloc(NULL, 0, NULL, 0);
|
|
if (pg == NULL)
|
|
panic("cpu_startup: not enough memory for "
|
|
"buffer cache");
|
|
pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
|
|
VM_PROT_READ|VM_PROT_WRITE);
|
|
curbuf += PAGE_SIZE;
|
|
curbufsize -= PAGE_SIZE;
|
|
}
|
|
}
|
|
pmap_update(pmap_kernel());
|
|
|
|
/*
|
|
* Allocate a submap for exec arguments. This map effectively
|
|
* limits the number of processes exec'ing at any time.
|
|
*/
|
|
exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
|
|
16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
|
|
/*
|
|
* Allocate a submap for physio.
|
|
*/
|
|
phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
|
|
VM_PHYS_SIZE, 0, FALSE, NULL);
|
|
|
|
/*
|
|
* (No need to allocate an mbuf cluster submap. Mbuf clusters
|
|
* are allocated via the pool allocator, and we use KSEG to
|
|
* map those pages.)
|
|
*/
|
|
|
|
format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
|
|
printf(", %s free", pbuf);
|
|
format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
|
|
printf(", %s in %d buffers\n", pbuf, nbuf);
|
|
|
|
/*
|
|
* Set up buffers, so they can be used to read disk labels.
|
|
*/
|
|
bufinit();
|
|
}
|
|
|
|
int
|
|
cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
int *name;
|
|
u_int namelen;
|
|
void *oldp;
|
|
size_t *oldlenp;
|
|
void *newp;
|
|
size_t newlen;
|
|
struct proc *p;
|
|
{
|
|
/* All sysctl names at this level are terminal. */
|
|
if (namelen != 1)
|
|
return ENOTDIR;
|
|
|
|
switch (name[0]) {
|
|
default:
|
|
return EOPNOTSUPP;
|
|
}
|
|
}
|
|
|
|
int waittime = -1;
|
|
|
|
void
|
|
cpu_reboot(howto, bootstr)
|
|
int howto;
|
|
char *bootstr;
|
|
{
|
|
|
|
/* Take a snapshot before clobbering any registers. */
|
|
if (curproc)
|
|
savectx((struct user *)curpcb);
|
|
|
|
if (cold) {
|
|
howto |= RB_HALT;
|
|
goto haltsys;
|
|
}
|
|
|
|
/* If "always halt" was specified as a boot flag, obey. */
|
|
if (boothowto & RB_HALT)
|
|
howto |= RB_HALT;
|
|
|
|
boothowto = howto;
|
|
if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
|
|
waittime = 0;
|
|
vfs_shutdown();
|
|
|
|
/*
|
|
* If we've been adjusting the clock, the todr
|
|
* will be out of synch; adjust it now.
|
|
*/
|
|
resettodr();
|
|
}
|
|
|
|
splhigh();
|
|
|
|
if (howto & RB_DUMP)
|
|
dumpsys();
|
|
|
|
haltsys:
|
|
doshutdownhooks();
|
|
|
|
if (howto & RB_HALT) {
|
|
printf("\n");
|
|
printf("The operating system has halted.\n");
|
|
printf("Please press any key to reboot.\n\n");
|
|
cnpollc(1); /* For proper keyboard command handling */
|
|
cngetc();
|
|
cnpollc(0);
|
|
}
|
|
|
|
printf("%s\n\n", ((howto & RB_HALT) != 0) ? "halted." : "rebooting...");
|
|
yamon_exit(boothowto);
|
|
printf("Oops, back from yamon_exit()\n\nResetting...");
|
|
|
|
REGVAL(MALTA_SOFTRES) = MALTA_GORESET;
|
|
|
|
/*
|
|
* Need a small delay here, otherwise we see the first few characters of
|
|
* the warning below.
|
|
*/
|
|
delay(80000);
|
|
|
|
printf("WARNING: reset failed!\nSpinning...");
|
|
|
|
for (;;)
|
|
/* spin forever */ ; /* XXX */
|
|
}
|