232 lines
5.4 KiB
C
232 lines
5.4 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)fiximp.c 1.1 94/10/31 SMI";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
#include <machine/asm_linkage.h>
|
|
#include <machine/reg.h>
|
|
#include <machine/psl.h>
|
|
#include <machine/trap.h>
|
|
#include <machine/mmu.h>
|
|
#include <mon/idprom.h>
|
|
*/
|
|
#include <sys/types.h>
|
|
#include <machine/param.h>
|
|
#include <machine/clock.h>
|
|
#include <mon/sunromvec.h>
|
|
#include <sun/openprom.h>
|
|
|
|
/*
|
|
* macro definitions for routines that form the OBP interface
|
|
*/
|
|
#define NEXT prom_nextnode
|
|
#define CHILD prom_childnode
|
|
#define GETPROP prom_getprop
|
|
#define GETPROPLEN prom_getproplen
|
|
|
|
/*
|
|
* The following variables are machine-dependent, and are used by boot
|
|
* and kadb. They may also be used by other standalones. Modify with caution!
|
|
*/
|
|
|
|
/*
|
|
* This variable is used in usec_delay(). See the chart in lib/sparc/misc.s.
|
|
* Srt0.s sets this value based on the actual runtime environment encountered.
|
|
* It's critical that the value be no SMALLER than required, e.g. the
|
|
* DELAY macro guarantees a MINIMUM delay, not a maximum.
|
|
*/
|
|
#define NWINDOWS_DEFAULT 8
|
|
#define VAC_DEFAULT 0 /* there is *no* vac */
|
|
#define VACSIZE_DEFAULT 2048
|
|
#define VACLINESIZE_DEFAULT 32
|
|
#define SEGMASK_DEFAULT 0x1ff
|
|
|
|
int Cpudelay = 0;
|
|
int nwindows = NWINDOWS_DEFAULT;
|
|
int vac = VAC_DEFAULT;
|
|
int vac_size = VACSIZE_DEFAULT;
|
|
int vac_linesize = VACLINESIZE_DEFAULT;
|
|
int segmask = SEGMASK_DEFAULT;
|
|
|
|
/*
|
|
* The next group of variables and routines handle the
|
|
* Open Boot Prom devinfo or property information.
|
|
*/
|
|
int debug_prop = 0; /* Turn on to enable debugging message */
|
|
|
|
#define CLROUT(a, l) \
|
|
{ \
|
|
register int c = l; \
|
|
register char *p = (char *)a; \
|
|
while (c-- > 0) \
|
|
*p++ = 0; \
|
|
}
|
|
|
|
#define CLRBUF(a) CLROUT(a, sizeof a)
|
|
|
|
static void searchtree(), findprop();
|
|
|
|
fiximp()
|
|
{
|
|
|
|
searchtree(NEXT(0)); /* Get the root node*/
|
|
}
|
|
|
|
static void
|
|
searchtree(curnode)
|
|
register int curnode;
|
|
{
|
|
#define MAXNAME 32
|
|
u_char tmp_name[MAXNAME];
|
|
|
|
for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) {
|
|
CLRBUF(tmp_name);
|
|
if ((void)getprop(curnode, "name", tmp_name) != -1) {
|
|
if (!strcmp(tmp_name, "processor")) {
|
|
findprop(curnode);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Can not find the "processor" node, use default value */
|
|
}
|
|
|
|
static void
|
|
findprop(curnode)
|
|
register int curnode;
|
|
{
|
|
(void)getprop(curnode, "ncaches", &vac);
|
|
(void)getprop(curnode, "mmu-nctx", &nwindows);
|
|
(void)getprop(0, "cache-nlines", &vac_size);
|
|
(void)getprop(0, "cache-linesize", &vac_linesize);
|
|
if (debug_prop) {
|
|
printf("nwindows %d\n", nwindows);
|
|
printf("vac %d\n", vac);
|
|
printf("cache-nlines %d\n", vac_size);
|
|
printf("cache_linesize %d\n", vac_linesize);
|
|
}
|
|
if (vac)
|
|
setcpudelay();
|
|
}
|
|
|
|
/*
|
|
* set delay constant for usec_delay()
|
|
* NOTE: we use the fact that the per-
|
|
* processor clocks are available and
|
|
* mapped properly at "utimers".
|
|
*/
|
|
static
|
|
setcpudelay()
|
|
{
|
|
register struct count14 *utimers = (struct count14 *)0;
|
|
register unsigned r; /* timer resolution, ~ns */
|
|
register unsigned e; /* delay time, us */
|
|
register unsigned es; /* delay time, ~ns */
|
|
register unsigned t; /* for time measurement */
|
|
int nreg, space, nrng;
|
|
addr_t paddr;
|
|
u_int tomap, base_addr;
|
|
int nodeid;
|
|
#define MAXRANGE 8
|
|
struct dev_reg dev_reg[MAXRANGE];
|
|
struct dev_reg dev_rng[MAXRANGE];
|
|
extern caddr_t prom_map();
|
|
|
|
#ifdef noneed
|
|
nrng = getnode(NEXT(0), "obio", dev_rng, &nodeid);
|
|
if (nrng) {
|
|
space = (int)dev_rng[0].reg_bustype;
|
|
base_addr = (u_int)dev_rng[0].reg_addr;
|
|
} else {
|
|
space = 0;
|
|
base_addr = 0;
|
|
}
|
|
|
|
if (nodeid) {
|
|
nreg = getreginfo(nodeid, "counter", dev_reg);
|
|
if (nreg) {
|
|
paddr = base_addr + dev_reg[0].reg_addr;
|
|
tomap = dev_reg[0].reg_size;
|
|
(int)utimers = (int)prom_map(COUNTER_ADDR,
|
|
space, paddr, tomap);
|
|
}
|
|
}
|
|
#endif noneed
|
|
|
|
if ((int)utimers == 0 || (int)utimers == -1)
|
|
utimers = (struct count14 *)COUNTER_ADDR;
|
|
r = 512; /* worst supported timer resolution */
|
|
es = r * 100; /* target delay in ~ns */
|
|
e = ((es+1023) >> 10); /* request delay in us, round up */
|
|
es = e << 10; /* adjusted target delay in ~ns */
|
|
Cpudelay = 1; /* initial guess */
|
|
DELAY(1); /* first time may be weird */
|
|
do {
|
|
Cpudelay <<= 1; /* double until big enough */
|
|
t = utimers->timer_lsw;
|
|
DELAY(e);
|
|
t = utimers->timer_lsw - t;
|
|
} while (t < es);
|
|
Cpudelay = (Cpudelay * es + t) / t;
|
|
if (Cpudelay < 0)
|
|
Cpudelay = 0;
|
|
}
|
|
|
|
#define MAXSYSNAME 32
|
|
int
|
|
getnode(curnode, namep, rngp, nodeidp)
|
|
int curnode;
|
|
char *namep;
|
|
struct dev_reg *rngp;
|
|
int *nodeidp;
|
|
{
|
|
register int nrng = 0;
|
|
u_char tmp_name[MAXSYSNAME];
|
|
|
|
for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) {
|
|
CLRBUF(tmp_name);
|
|
if (GETPROP(curnode, "name", tmp_name) != 1)
|
|
if (strcmp(tmp_name, namep))
|
|
continue;
|
|
else {
|
|
nrng = GETPROPLEN(curnode, "range") /
|
|
sizeof (struct dev_reg);
|
|
if (nrng > 0)
|
|
GETPROP(curnode, "range", rngp);
|
|
else
|
|
rngp = (struct dev_reg *)0;
|
|
*nodeidp = curnode;
|
|
return (nrng);
|
|
}
|
|
}
|
|
return (0);
|
|
}
|
|
int
|
|
getreginfo(curnode, namep, dev_reg)
|
|
int curnode;
|
|
char *namep;
|
|
struct dev_reg *dev_reg;
|
|
{
|
|
register int nreg = 0;
|
|
u_char tmp_name[MAXSYSNAME];
|
|
|
|
for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) {
|
|
CLRBUF(tmp_name);
|
|
if (GETPROP(curnode, "name", tmp_name) != 1)
|
|
if (strcmp(tmp_name, namep))
|
|
continue;
|
|
nreg = GETPROPLEN(curnode, "reg") / sizeof (struct dev_reg);
|
|
if (nreg > 0)
|
|
GETPROP(curnode, "reg", dev_reg);
|
|
else
|
|
dev_reg = (struct dev_reg *)0;
|
|
break;
|
|
}
|
|
return (nreg);
|
|
}
|