daktari.c revision 13bb89069ebe3cbce237b2708bda9946a2ff4607
/*
* 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;
/*
* Table that maps memory slices to a specific memnode.
*/
/*
* 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 */
}
/*ARGSUSED*/
void
{}
/*
*/
static void
{
int mnode;
/*
* First see if this board already has a memnode associated
* with it. If not, see if this slice has a memnode. This
* covers the cases where a single slice covers multiple
* boards (cross-board interleaving) and where a single
* board has multiple slices (1+GB DIMMs).
*/
mnode = mem_node_alloc();
}
}
}
/*
* 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.
*/
}
}
}
/*
* This routine is run midway through the boot process. By the time we get
* here, we know about all the active CPU boards in the system, and we have
* extracted information about each board's memory from the memory
* controllers. We have also figured out which ranges of memory will be
* assigned to which memnodes, so we walk the slice table to build the table
* of memnodes.
*/
/* ARGSUSED */
void
{
int slice;
continue;
}
}
/*
* Daktari support for lgroups.
*
* On Daktari, an lgroup platform handle == slot number.
*
* Mappings between lgroup handles and memnodes are managed
* in addition to mappings between memory slices and memnodes
* to support cross-board interleaving as well as multiple
* slices per board (e.g. >1GB DIMMs). The initial mapping
* of memnodes to lgroup handles is determined at boot time.
*/
int
{
}
/*
* Return the platform handle for the lgroup containing the given CPU
*
* For Daktari, lgroup platform handle == slot number
*/
{
return (DAK_GETSLOT(id));
}
/*
* Platform specific lgroup initialization
*/
void
plat_lgrp_init(void)
{
int i;
/*
* Initialize lookup tables to invalid values so we catch
* any illegal use of them.
*/
for (i = 0; i < DAK_MAX_SLICE; i++) {
slice_to_memnode[i] = -1;
}
}
/*
* Return latency between "from" and "to" lgroups
*
* This latency number can only be used for relative comparison
* between lgroups on the running system, cannot be used across platforms,
* and may not reflect the actual latency. It is platform and implementation
* specific, so platform gets to decide its value. It would be nice if the
* number was at least proportional to make comparisons more meaningful though.
* NOTE: The numbers below are supposed to be load latencies for uncached
* memory divided by 10.
*/
int
{
/*
* Return min remote latency when there are more than two lgroups
* (root and child) and getting latency between two different lgroups
* or root is involved
*/
return (21);
else
return (19);
}
/*
* 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;
}