daktari.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <sys/platform_module.h>
#include <sys/machsystm.h>
/* I2C Stuff */
int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
/* Daktari Keyswitch Information */
#define DAK_KEY_POLL_PORT 3
#define DAK_KEY_POLL_BIT 2
#define DAK_KEY_POLL_INTVL 10
static boolean_t key_locked_bit;
static clock_t keypoll_timeout_hz;
/*
* For software memory interleaving support.
*/
static uint64_t
#define SLICE_PA 0
#define SLICE_SPAN 1
extern void (*abort_seq_handler)();
static int daktari_dev_search(dev_info_t *, void *);
static void keyswitch_poll(void *);
static void daktari_abort_seq_handler(char *msg);
void
startup_platform(void)
{
/*
* Disable an active h/w watchdog timer
* upon exit to OBP.
*/
extern int disable_watchdog_on_exit;
}
int
{
return (0);
}
#pragma weak mmu_init_large_pages
void
set_platform_defaults(void)
{
extern int ts_dispatch_extended;
extern uchar_t *ctx_pgsz_array;
extern void mmu_init_large_pages(size_t);
/*
* Use the alternate TS dispatch table for USIII+ forward,
* which is better tuned for large servers.
*/
ts_dispatch_extended = 1;
if ((mmu_page_sizes == max_mmu_page_sizes) &&
(mmu_ism_pagesize != MMU_PAGESIZE32M)) {
if (&mmu_init_large_pages)
}
}
void
load_platform_modules(void)
{
}
}
}
void
load_platform_drivers(void)
{
char **drv;
static char *boot_time_drivers[] = {
"hpc3130",
"todds1287",
"mc-us3",
"ssc050",
"pcisch",
};
*drv);
}
/*
* mc-us3 & ssc050 must stay loaded for plat_get_mem_unum()
* and keyswitch_poll()
*/
/* Gain access into the ssc050_get_port function */
daktari_ssc050_get_port_bit = (int (*) (dev_info_t *, int, int,
if (daktari_ssc050_get_port_bit == NULL) {
return;
}
}
static int
{
int *dev_regs; /* Info about where the device is. */
int err;
return (DDI_WALK_CONTINUE);
if (err != DDI_PROP_SUCCESS) {
return (DDI_WALK_CONTINUE);
}
/*
* regs[0] contains the bus number and regs[1]
* contains the device address of the i2c device.
* 0x82 is the device address of the i2c device
* from which the key switch position is read.
*/
return (DDI_WALK_TERMINATE);
}
} else {
}
return (DDI_WALK_CONTINUE);
}
static void
keyswitch_poll(void *arg)
{
int port = DAK_KEY_POLL_PORT;
int bit = DAK_KEY_POLL_BIT;
int err;
&port_byte, I2C_NOSLEEP);
if (err != 0) {
return;
}
}
static void
daktari_abort_seq_handler(char *msg)
{
if (key_locked_bit == 0)
"ignoring debug enter sequence");
else {
}
}
int
{
return (ENOTSUP);
}
int
{
return (ENOTSUP);
}
/*
* memory controller's address range.
*/
static int
{
return (bd);
}
}
}
}
/* NOTREACHED */
}
/*
* This index is used to associate a given pfn to a place on the freelist.
* This results in dispersing pfn assignment over all the boards in the
* system.
* Choose the index randomly to prevent clustering pages of different
* colors on the same board.
*/
/*
* Theory of operation:
* - When the system walks the prom tree, it calls the platform
* function plat_fill_mc() for each memory-controller node found
* in map_wellknown().
* - The plat_fill_mc() function interrogates the memory controller
* to find out if it controls memory. If it does, the physical
* address and span are recorded in a lookup table.
* - During VM init, the VM calls plat_freelist_process() to shuffle
* the page freelists. This is done after the page freelists are
* coalesced, but before the system goes live, since we need to be
* able to get the exclusive lock on all the pages.
* - plat_freelist_process() removes all pages from the freelists,
* and sorts them out into per-board freelists. It does this by
* using the lookup table that was built earlier. It then
* round-robins across the per-board freelists and frees each page,
* leaving an even distribution of pages across the system.
*/
void
{
int mtype;
/*
* Sort through freelists one memory type and size at a time.
*/
/*
* Compute the maximum # of phys colors based on
* page size.
*/
/*
* Sort through freelists one color at a time.
*/
bd_cnt = 0;
bd_flags = 0;
}
continue;
/*
* Acquire per-color freelist lock.
*/
/*
* Go through freelist, sorting pages out
* into per-board lists.
*/
while (*freelist) {
/*
* Delete from freelist.
*/
if (size != 0) {
} else {
}
if (pfn < slice_start ||
&slice_start, &slice_end);
/*
* Add to per-board list.
*/
if (size != 0) {
} else {
page);
}
/*
* Seen this board yet?
*/
bd_cnt++;
}
}
/*
* Make the sortlist so
* bd_cnt choices show up
*/
bds = 0;
}
/*
* Set random start.
*/
(void) random_idx(-color);
/*
* now rebuild the freelist by shuffling
* pages from bd lists
*/
while (bd_cnt) {
/*
* get "random" index between 0 &
* bd_cnt
*/
/*
* Delete from sort list and add
* to freelist.
*/
if (size != 0) {
} else {
page);
}
if (pfn < slice_start ||
&slice_start, &slice_end);
/*
* Is this the last page this list?
*/
--bd_cnt;
/*
* redo the sortlist so only
* bd_cnt choices show up
*/
bds = 0;
for (idy = 0;
idy < DAK_SBD_SLOTS;
idy++) {
}
}
}
}
}
}
}
}
/*
* If ubound > 0, will return an int between 0 & ubound
* If ubound < 0, will set "random seed"
*/
static uint_t
random_idx(int ubound)
{
static int idx = 0;
if (ubound > 0) {
return (idx);
}
return (0);
}
/*
*/
static void
{
}
/*
* Dynamically detect memory slices in the system by decoding
* the cpu memory decoder registers at boot time.
*/
void
{
int len;
int local_mc;
int portid;
int boardid;
int cpuid;
int i;
(portid == -1))
return;
/*
* Decode the board number from the MC portid. Assumes
* portid == safari agentid.
*/
/*
* The "reg" property returns 4 32-bit values. The first two are
* combined to form a 64-bit address. The second two are for a
* 64-bit size, but we don't actually need to look at that value.
*/
prom_printf("Warning: malformed 'reg' property\n");
return;
}
return;
/*
* Figure out whether the memory controller we are examining
* belongs to this CPU or a different one.
*/
local_mc = 1;
else
local_mc = 0;
for (i = 0; i < DAK_BANKS_PER_MC; i++) {
/*
* Memory decode masks are at offsets 0x10 - 0x28.
*/
/*
* If the memory controller is local to this CPU, we use
* the special ASI to read the decode registers.
* Otherwise, we load the values from a magic address in
* I/O space.
*/
if (local_mc)
else
/*
* If the upper bit is set, we have a valid mask
*/
/*
* The memory decode register is a bitmask field,
* so we can decode that into both a base and
* a span.
*/
}
}
}
/*
* No platform drivers on this platform
*/
char *platform_module_list[] = {
(char *)0
};
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
int
{
else
return (ENOTSUP);
}
/*
* This platform hook gets called from mc_add_mem_unum_label() in the mc-us3
* driver giving each platform the opportunity to add platform
* specific label information to the unum for ECC error logging purposes.
*/
void
{
char old_unum[UNUM_NAMLEN];
}
int
{
return (ENOSPC);
} else {
return (0);
}
}
/*
* The zuluvm module requires a dmv interrupt for each installed zulu board.
*/
void
{
*hwint = 0;
}