mem_addr.c revision ee9ef9e5478646701c1f0cc347324b1c7bad1efa
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/cpu_module_impl.h>
#include "intel_nhm.h"
#include "nhm_log.h"
struct sad {
char mode;
char enable;
char interleave;
} sad[MAX_SAD_DRAM_RULE];
struct tad {
char mode;
char enable;
char interleave;
struct sag_ch {
char divby3;
char remove6;
char remove7;
char remove8;
struct rir {
struct rir_way {
} way[MAX_RIR_WAY];
char interleave;
char closed_page;
char ecc_enabled;
char lockstep[2];
char mirror_mode[2];
char spare_channel[2];
static int
int *no_interleave_p)
{
int way;
int c;
int i;
int lc;
int rt = 0;
int start = 0;
*no_interleave_p = 0;
if (channel > 1)
return (0);
else
return (1);
}
lc = -1;
c = 1 << channel;
for (i = 0; i < CHANNELS_PER_MEMORY_CONTROLLER; i++) {
if ((CHANNEL_MAP(mc_channel_mapper, i, 0) & c) != 0) {
lc = i;
break;
}
}
if (lc == -1) {
for (i = 0; i < CHANNELS_PER_MEMORY_CONTROLLER; i++) {
lc = i;
break;
}
}
}
if (lc == -1) {
return (0);
}
*way_p = 0;
*no_interleave_p = 0;
start = 4;
if (way == 0) {
c = TAD_INTERLEAVE(
if (lc != c) {
break;
}
}
if (i == INTERLEAVE_NWAY)
*no_interleave_p = 1;
}
rt = 1;
break;
}
}
return (rt);
}
int
{
int i;
int node = -1;
int way;
base = 0;
for (i = 0; i < MAX_SAD_DRAM_RULE; i++) {
case 0:
break;
case 1:
break;
case 2:
break;
default:
return (-1);
}
if (interleave_p)
if (package == 1)
node = 0;
else if (package == 2)
node = 1;
else
node = -1;
break;
}
}
return (node);
}
static uint64_t
{
channel = 0;
(addr & 0xffc0);
}
}
}
(caddr & 0x3f);
}
return (caddr);
}
int
int *interleave_p)
{
int i;
int channel = -1;
int way;
base = 0;
for (i = 0; i < MAX_TAD_DRAM_RULE; i++) {
case 0:
break;
case 1:
break;
case 2:
break;
default:
return (-1);
}
if (channel_addrp) {
i, addr);
}
if (interleave_p)
break;
}
}
switch (lc) {
case 1:
channel = 0;
break;
case 2:
channel = 1;
break;
case 4:
channel = 2;
break;
case 3: /* mirror PCH0 and PCH1 */
if (!write) {
channel = 1;
else
channel = 0;
}
break;
case 5: /* sparing PCH0 to PCH2 */
channel = 0;
break;
case 6: /* sparing PCH1 to PCH2 */
channel = 1;
break;
}
}
return (channel);
}
int
{
int node;
int sinterleave;
if (sinterleave == 1) {
channels = 0;
} else {
channels = 0;
channels1 = 0;
}
return (channels);
}
int
{
int i;
int rank;
int dimm;
int way;
dimm = -1;
rank = -1;
base = 0;
rank_addr = -1ULL;
for (i = 0; i < MAX_TAD_DRAM_RULE; i++) {
if (closed_page) {
VRANK_SZ) /
} else {
VRANK_SZ) /
}
break;
}
}
*rank_addr_p = rank_addr;
return (dimm);
}
static int
int *way_p)
{
int i, j;
int ot = 0;
int mode;
int start;
int rt = 1;
int found = 0;
channel = 0;
base = 0;
for (i = 0; i < MAX_SAD_DRAM_RULE; i++) {
if (mode == 2) {
for (j = 0; j < INTERLEAVE_NWAY; j++) {
j);
ot++;
if (found) {
rt = 2;
break;
}
} else {
found = 1;
if (ot) {
rt = 2;
break;
}
}
}
} else {
if (mode == 2)
else
start = 0;
for (j = start; j < INTERLEAVE_NWAY; j++) {
j);
ot++;
if (found) {
rt = 2;
break;
}
} else if (!found) {
xc = TAD_INTERLEAVE(
j);
*way_p = j;
if (ot) {
rt = 2;
break;
}
found = 1;
}
}
}
}
break;
}
}
return (rt);
}
{
int i;
int lchannel;
int bits;
int no_interleave;
int sinterleave;
int cinterleave;
int rinterleave;
int found = 0;
lchannel = 0;
else
addr = -1;
base = 0;
for (i = 0; i < MAX_TAD_DRAM_RULE && found == 0; i++) {
continue;
if (closed_page) {
} else {
}
base) / rinterleave;
found = 1;
if (rank_interleave_p) {
}
if (rank_way_p)
*rank_way_p = way;
break;
}
}
}
}
if (!found)
return (-1ULL);
base = 0;
for (i = 0; i < MAX_TAD_DRAM_RULE; i++) {
way = 0;
&no_interleave)) {
bits = 0;
(addr & 0x3f);
}
bits = 1;
}
}
}
if (socket_interleave_p) {
}
if (socket_way_p)
*socket_way_p = way;
cinterleave = 1;
} else {
}
if (channel_interleave_p) {
}
(cinterleave * sinterleave *
}
if (rank_sz_p) {
}
if (rank_base_p)
*rank_base_p = baddr;
if (channel_way_p)
*channel_way_p = way;
break;
}
case 0:
break;
case 1:
break;
case 2:
if (sinterleave == 1) {
(((addr >> 6) &
0x3ffffffff) % 3);
else
switch (xway) {
case 0:
way = 0;
break;
case 5:
way = 1;
break;
case 2:
way = 2;
break;
case 4:
way = 3;
break;
case 1:
way = 4;
break;
case 6:
way = 5;
break;
}
} else {
(((addr >> 6) &
0x3ffffffff) % 3);
if (xway < 0)
xway += 3;
switch (xway) {
case 0:
way = 0;
break;
case 1:
way = 1;
break;
case 2:
way = 2;
break;
}
}
break;
}
break;
}
}
}
return (addr);
}
/*ARGSUSED*/
static cmi_errno_t
{
int node;
int channel;
int dimm;
int rank;
if (node == -1)
return (CMIERR_UNKNOWN);
if (channel == -1)
return (CMIERR_UNKNOWN);
if (dimm == -1)
return (CMIERR_UNKNOWN);
unump->unum_board = 0;
return (CMI_SUCCESS);
}
/*ARGSUSED*/
static cmi_errno_t
{
int node;
int channel;
int rank;
int i;
long v;
&hcsp) != 0)
return (CMIERR_UNKNOWN);
if (nvlist_lookup_uint64(hcsp,
&rank_addr) != 0) {
if (nvlist_lookup_uint64(hcsp,
FM_FMRI_HC_SPECIFIC_PHYSADDR, &pa) == 0) {
return (CMI_SUCCESS);
}
return (CMIERR_UNKNOWN);
}
return (CMIERR_UNKNOWN);
node = -1;
channel = -1;
rank = -1;
for (i = 0; i < npr; i++) {
&hcnm) != 0 ||
&hcid) != 0 ||
return (CMIERR_UNKNOWN);
node = (int)v;
channel = (int)v;
rank = (int)v;
}
return (CMIERR_UNKNOWN);
} else {
}
0);
if (pa == -1) {
rt = CMIERR_UNKNOWN;
} else {
rt = CMI_SUCCESS;
}
return (rt);
}
static const cmi_mc_ops_t nhm_mc_ops = {
nhm_error_trap /* cmi_mc_logout */
};
/*ARGSUSED*/
int
{
return (CMI_HDL_WALK_NEXT);
}
static int
choose_cpu(int *lastslot_p)
{
int first;
int last;
first = 0;
last = 1;
}
} else {
first = 1;
}
*lastslot_p = last;
return (first);
}
static int
{
int rt = 1;
int i, j;
int p;
for (i = 1; i < INTERLEAVE_NWAY; i++) {
p = SAD_INTERLEAVE(list, i);
for (j = 0; j < i; j++) {
if (p == SAD_INTERLEAVE(list, j))
break;
}
if (i == j)
rt++;
}
return (rt);
}
static int
{
int rt = 1;
int i, j;
int c;
for (i = 1; i < INTERLEAVE_NWAY; i++) {
c = TAD_INTERLEAVE(list, i);
for (j = 0; j < i; j++) {
if (c == TAD_INTERLEAVE(list, j))
break;
}
if (i == j)
rt++;
}
return (rt);
}
static void
{
int k, l;
if (rank_addr == 0)
return;
for (k = 0; k <= rule; k++) {
for (l = 0; l < way; l++) {
}
}
}
}
void
{
int i, j, k, l, m;
int nhm_slot;
int nhm_lastslot;
for (i = 0; i < MAX_SAD_DRAM_RULE; i++) {
}
for (i = nhm_slot; i < nhm_lastslot; i++) {
if (MC_CPU_RAS_RD(i) == NHM_CPU_RAS) {
lockstep[i] = 1;
mirror_mode[i] = 1;
}
spare_channel[i] = 1;
for (j = 0; j < MAX_TAD_DRAM_RULE; j++) {
tad_dram_rule = TAD_DRAM_RULE_RD(i, j);
TAD_INTERLEAVE_LIST_RD(i, j);
if (mirror_mode[i] || lockstep[i]) {
} else {
tad[i][j].interleave =
if (spare_channel[i] &&
tad[i][j].interleave ==
tad[i][j].interleave--;
}
}
for (j = 0; j < CHANNELS_PER_MEMORY_CONTROLLER; j++) {
m = 0;
base = 0;
for (k = 0; k < MAX_TAD_DRAM_RULE; k++) {
rir_limit = MC_RIR_LIMIT_RD(i, j, k);
for (l = 0; l < MAX_RIR_WAY; l++) {
rir_way = MC_RIR_WAY_RD(i, j, m);
m++;
}
} else {
}
for (l = 0; l < MAX_RIR_WAY; l++) {
set_rank(i, j, k, l,
base) /
rir[i][j][k].interleave));
}
}
}
}
ecc_enabled = 1;
}