* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: decode.c
* Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
* 4150 Network Circle, Santa Clara, California 95054, U.S.A.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* For the avoidance of doubt, and except that if any non-GPL license
* choice is available it will apply instead, Sun elects to use only
* the General Public License version 2 (GPLv2) at this time for any
* software where a choice of GPL license versions is made
* available with the language indicating that GPLv2 or any later version
* may be used, or where a choice of which version of the GPL is applied is
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* ========== Copyright Header End ============================================
#define DUAL_CHANNEL 0x100
#define SNG_CHANNEL 0x200
#define STACK_DIMM 0x1000
#define PARTIAL_BANK_2BK 0x20000
#define PARTIAL_BANK_4BK 0x40000
char *bank_set_mask_val
= 0;
unsigned int bank_set_mask
= 0;
bank_set_mask_val
=mc_scan_plusargs("bank_set_mask=");
bank_set_mask
=strtoul(bank_set_mask_val
, 0, 16);
long long pm_address_shift(long long addr
, int shift
)
int bank_set_mask
= get_bank_set_mask();
shifted_addr
= addr
<< shift
;
shifted_addr
= shifted_addr
>> 9;
shifted_addr
= (shifted_addr
<< 1) | pa8
;
shifted_addr
= (shifted_addr
<< 1) | pa7
;
shifted_addr
= (shifted_addr
<< 1) | pa6
;
shifted_addr
= (shifted_addr
<< 6) | (addr
& 0x3f);
int pm_bank_s(long long addr
, int shift
)
addr
= pm_address_shift(addr
, shift
);
bank_s
= (addr
>> 7) & 0x3;
long long fc_hash_pa(long long addr
, int dimm_config
)
long long hashed_pa
= addr
;
long long hashed_pa_17_11
= 0;
if(dimm_config
& HASH_PA
)
if(addr
& 0x8000000000) // if PA[39] = 1, return addr
pa_32_28
= ((addr
& 0x1f0000000) >> 28);
pa_17_13
= ((addr
& 0x3e000) >> 13);
pa_19_18
= ((addr
& (0x3 << 18)) >> 18);
pa_12_11
= ((addr
& (0x3 << 11)) >> 11);
//io_printf((char *)" pa_32_28 = %llx, pa_17_13 = %llx, pa_19_18 = %llx, pa_12_11 = %llx \n", pa_32_28, pa_17_13, pa_19_18, pa_12_11);
hashed_pa_17_11
= (pa_32_28
^ pa_17_13
);
hashed_pa_17_11
= (hashed_pa_17_11
<< 2) | (pa_19_18
^ pa_12_11
);
hashed_pa
= (hashed_pa
& 0xfffffc07ff) | (hashed_pa_17_11
<< 11);
//io_printf((char *)" ADDR = %llx, HASHED_PA = %llx\n",addr, hashed_pa);
long long address_decode(long long *addr
, int dimm_config
, int shift
)
dway = RAS[14:0], CAS[10:2], BA[2:0], CAS[1:0]
[28:14] [13:5] [4:2] [1:0]
dway = RAS[14:0], CAS[10:3], BA[2:0], CAS[2:0]
[28:14] [13:6] [5:3] [2:0]
int msb_cas_bits_count
= 0;
//io_printf("-->before pm_address_shift, addr is %016llx\n",saddr);
saddr
= pm_address_shift(saddr
, shift
);
//io_printf("-->after pm_address_shift, addr is %016llx\n",saddr);
saddr
= fc_hash_pa(saddr
, dimm_config
);
//io_printf("-->after fc_hash_pa, addr is %016llx\n",saddr);
//io_printf((char *)" entering address_decode. addr=%llx, dimm_config=%d\n",(saddr),dimm_config);
if(dimm_config
& DUAL_CHANNEL
)
if(dimm_config
& RANK_HIGH
) // 2-ch Rank-high, Rank-dimm, Stack-dimm
if(dimm_config
& DIMM_CONF_8
)
else if(dimm_config
& DIMM_CONF_6
)
else if(dimm_config
& DIMM_CONF_4
)
else if(dimm_config
& DIMM_CONF_2
)
if (dimm_config
& DIMM_1G
) { // 1G
if (dimm_config
& DIMM_512
) { // 2G
dimm_addr
= (((saddr
) & ((0xffffffffff) >> (5 - dimm_addr_bits
))) >> 35);
dway
= ((saddr
) & ((0xffffffffff) >> 6)) >> 11; // RAS[14:0], CAS[10:3]
dway
= (dway
<< 1) | (((saddr
) >> 34) & 1); // CAS[2]
// last 5 bits are BA[2],BA[1],BA[0],PA[5],PA[4]
// last 3 bits are common hence assigned in the end
dway
= (dway
<< 2) | (((saddr
) >> 9) & 3); // BA[2:1]
dimm_addr
= (((saddr
) & ((0xffffffffff) >> (6 - dimm_addr_bits
))) >> 34);
dway
= ((saddr
) & ((0xffffffffff) >> 7)) >> 11; // RAS[13:0], CAS[10:3]
dway
= (dway
<< 1) | (((saddr
) >> 33) & 1); // CAS[2]
// last 5 bits are BA[2],BA[1],BA[0],PA[5],PA[4]
// last 3 bits are common hence assigned in the end
dway
= (dway
<< 2) | (((saddr
) >> 9) & 3); // BA[2:1]
dimm_addr
= (((saddr
) & ((0xffffffffff) >> (8 - (dimm_config
& 0xf) - dimm_addr_bits
))) >> (32 + (dimm_config
& 0xf)));
dway
= ((saddr
) & ((0xffffffffff) >> (8 - (dimm_config
& 0xf)))) >> 10; // RAS[13,12:0], CAS[10:2]
// last 5 bits are 0,BA[1],BA[0],PA[5],PA[4]
// last 3 bits are common hence assigned in the end
dway
= (dway
<< 1) | (((saddr
) >> 9) & 1); // BA[1]
dway
= (dway
<< 1) | (((saddr
) >> 6) & 1); // BA[1]
dway
= (dway
<< 2) | (((saddr
) >> 4) & 3); // PA[5:4]
//io_printf((char *)"dimm_addr = %x, dway = %llx\n",dimm_addr, dway);
dway
|= (dimm_addr
<< 29);
else if(dimm_config
& RANK_LOW
) // 2-ch rank-low
if(dimm_config
& DIMM_CONF_8
)
else if(dimm_config
& DIMM_CONF_6
)
else if(dimm_config
& DIMM_CONF_4
)
else if(dimm_config
& DIMM_CONF_2
)
if(dimm_config
& RANK_DIMM
)
if(dimm_config
& DIMM_1G
) { // 1G or 2G
if(dimm_config
& DIMM_512
) // 2G
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0xf); // CAS[5:2]
dimm_addr
= (((saddr
) >> 11) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x7); // CAS[4:2]
dimm_addr
= (((saddr
) >> 11) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x3); // CAS[3:2]
dimm_addr
= (((saddr
) >> 11) & 0x1);
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x1); // CAS[2]
dway
= ((saddr
) & (0xffffffffff >> (6 + dimm_adjust
))) >> lsb_mask
; // RAS[14,13:0], CAS[10:6,5,4,3]
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x3); // BA[2:1]
dway
= (dway
<< 2) | bank_addr
;
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x7); // CAS[4:2]
dimm_addr
= (((saddr
) >> 10) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x3); // CAS[3:2]
dimm_addr
= (((saddr
) >> 10) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x1); // CAS[2]
dimm_addr
= (((saddr
) >> 10) & 0x1);
dway
= ((saddr
) & (0xffffffffff >> (7 + dimm_adjust
))) >> lsb_mask
; // RAS[13,12:0], CAS[10:5,4,3,2]
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x1); // BA[1]
dway
= (dway
<< 1); // 0 for BA[2]
dway
= (dway
<< 1) | bank_addr
;
dway
= (dway
<< 1) | (((saddr
) >> 6) & 1); // BA[0]
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // PA[5:4]
dway
|= (dimm_addr
<< 29);
else if(dimm_config
& STACK_DIMM
)
if(dimm_config
& DIMM_1G
) { // 1G and 2G
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x1f); // CAS[6:2]
dimm_addr
= (((saddr
) >> 11) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0xf); // CAS[5:2]
dimm_addr
= (((saddr
) >> 11) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x7); // CAS[4:2]
dimm_addr
= (((saddr
) >> 11) & 0x1);
msb_cas
= (((saddr
) >> (34 - dimm_adjust
)) & 0x3); // CAS[3:2]
dway
= ((saddr
) & (0xffffffffff >> (6 + dimm_adjust
))) >> lsb_mask
; // RAS[14,13:0], CAS[10:7,6,5,4]
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x3); // BA[2:1]
dway
= (dway
<< 2) | bank_addr
;
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0xf); // CAS[5:2]
dimm_addr
= (((saddr
) >> 10) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x7); // CAS[4:2]
dimm_addr
= (((saddr
) >> 10) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x3); // CAS[3:2]
dimm_addr
= (((saddr
) >> 10) & 0x1);
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x1); // CAS[2]
dway
= ((saddr
) & (0xffffffffff >> (7 + dimm_adjust
))) >> lsb_mask
; // RAS[13,12:0], CAS[10:6,5,4,3]
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x1); // BA[1]
dway
= (dway
<< 1); // 0 for BA[2]
dway
= (dway
<< 1) | bank_addr
;
dway
= (dway
<< 1) | (((saddr
) >> 6) & 1); // BA[0]
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // PA[5:4]
dway
|= (dimm_addr
<< 29);
if(dimm_config
& RANK_HIGH
) // 1-ch Rank-high, rank-dimm, stack-dimm
if(dimm_config
& DIMM_CONF_8
)
else if(dimm_config
& DIMM_CONF_6
)
else if(dimm_config
& DIMM_CONF_4
)
else if(dimm_config
& DIMM_CONF_2
)
if (dimm_config
& DIMM_1G
) { // 1G & 2G
if (dimm_config
& DIMM_512
)
dimm_addr
= (((saddr
) & ((0xffffffffff) >> (6 + dimm_adjust
- dimm_addr_bits
))) >> (34 - dimm_adjust
));
dway
= ((saddr
) & ((0xffffffffff) >> (7 + dimm_adjust
))) >> 11;
dway
= (dway
<< 1) | (((saddr
) >> (33 - dimm_adjust
)) & 1);
// last 6 bits are BA[2],BA[1],BA[0],CAS[2],CAS[1],CAS[0]
dway
= (dway
<< 2) | (((saddr
) >> 9) & 3); // BA[2:1]
dway
= (dway
<< 1) | (((saddr
) >> 6) & 1); // BA[0]
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
dimm_addr
= (((saddr
) & ((0xffffffffff) >> (9 - (dimm_config
& 0xf) - dimm_addr_bits
))) >> (31 + (dimm_config
& 0xf)));
dway
= ((saddr
) & ((0xffffffffff) >> (9 - (dimm_config
& 0xf)))) >> 10;
// last 6 bits are BA[2],BA[1],BA[0],CAS[2],CAS[1],CAS[0]
dway
= (dway
<< 1); // BA[2]
dway
= (dway
<< 1) | (((saddr
) >> 9) & 1); // BA[1]
dway
= (dway
<< 1) | (((saddr
) >> 6) & 1); // BA[0]
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
//io_printf((char *)"dimm_addr = %x, dway = %llx\n",dimm_addr, dway);
dway
|= (dimm_addr
<< 29);
else if(dimm_config
& RANK_LOW
) // 1-ch rank-low
if(dimm_config
& DIMM_CONF_8
)
else if(dimm_config
& DIMM_CONF_6
)
else if(dimm_config
& DIMM_CONF_4
)
else if(dimm_config
& DIMM_CONF_2
)
if(dimm_config
& RANK_DIMM
)
if(dimm_config
& DIMM_1G
) { // 1G & 2G
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0xf);
dimm_addr
= (((saddr
) >> 11) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x7);
dimm_addr
= (((saddr
) >> 11) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x3);
dimm_addr
= (((saddr
) >> 11) & 0x1);
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x1);
dway
= ((saddr
) & (0xffffffffff >> (7 + dimm_adjust
))) >> lsb_mask
;
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x3);
bank_addr
= (bank_addr
<< 1) | (((saddr
) >> 6) & 1);
dway
= (dway
<< 3) | bank_addr
;
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x7);
dimm_addr
= (((saddr
) >> 10) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x3);
dimm_addr
= (((saddr
) >> 10) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x1);
dimm_addr
= (((saddr
) >> 10) & 0x1);
dway
= ((saddr
) & (0xffffffffff >> (8 + dimm_adjust
))) >> lsb_mask
;
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x1);
bank_addr
= (bank_addr
<< 1) | (((saddr
) >> 6) & 1);
dway
= (dway
<< 1); // BA[2]
dway
= (dway
<< 2) | (bank_addr
& 0x3);
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
dway
|= (dimm_addr
<< 29);
else if(dimm_config
& STACK_DIMM
)
if(dimm_config
& DIMM_1G
) { // 1G and 2G
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x1f);
dimm_addr
= (((saddr
) >> 11) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0xf);
dimm_addr
= (((saddr
) >> 11) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x7);
dimm_addr
= (((saddr
) >> 11) & 0x1);
msb_cas
= (((saddr
) >> (33 - dimm_adjust
)) & 0x3);
dway
= ((saddr
) & (0xffffffffff >> (7 + dimm_adjust
))) >> lsb_mask
;
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x3);
bank_addr
= (bank_addr
<< 1) | (((saddr
) >> 6) & 1);
dway
= (dway
<< 3) | bank_addr
;
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0xf);
dimm_addr
= (((saddr
) >> 10) & 0x7);
else if(dimm_config
& DIMM_CONF_4
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x7);
dimm_addr
= (((saddr
) >> 10) & 0x3);
else if(dimm_config
& DIMM_CONF_2
) {
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x3);
dimm_addr
= (((saddr
) >> 10) & 0x1);
msb_cas
= (((saddr
) >> (32 - dimm_adjust
)) & 0x1);
dway
= ((saddr
) & (0xffffffffff >> (8 + dimm_adjust
))) >> lsb_mask
;
dway
= (dway
<< msb_cas_bits_count
) | msb_cas
;
bank_addr
= (((saddr
) >> 9) & 0x1);
bank_addr
= (bank_addr
<< 1) | (((saddr
) >> 6) & 1);
dway
= (dway
<< 1); // BA[2]
dway
= (dway
<< 2) | (bank_addr
& 0x3);
dway
= (dway
<< 2) | (((saddr
) >> 4) & 0x3); // CAS[2], CAS[1]
dway
= (dway
<< 1); // CAS[0]
dway
|= (dimm_addr
<< 29);
//io_printf((char *)" returning dway=%llx\n",dway);
long long decode_cs(long long *addr
, int dimm_config
, int shift
)
int channel_adjust
= 0, bit_adjust
= 0;
saddr
= pm_address_shift(saddr
, shift
);
saddr
= fc_hash_pa(saddr
, dimm_config
);
//io_printf((char *)" cs_decode, addr=%llx, dimm_config=%d\n",saddr,dimm_config);
if(dimm_config
& RANK_DIMM
)
if(dimm_config
& RANK_HIGH
)
if(dimm_config
& DUAL_CHANNEL
)
if(dimm_config
& DIMM_1G
)
if(dimm_config
& DIMM_512
)
else if(dimm_config
& DIMM_512
)
if(dimm_config
& DIMM_CONF_8
)
cs
= ((saddr
) >> (38 - channel_adjust
- bit_adjust
)) & 0x1;
else if(dimm_config
& DIMM_CONF_4
)
cs
= ((saddr
) >> (37 - channel_adjust
- bit_adjust
)) & 0x1;
else if(dimm_config
& DIMM_CONF_2
)
cs
= ((saddr
) >> (36 - channel_adjust
- bit_adjust
)) & 0x1;
cs
= ((saddr
) >> (35 - channel_adjust
- bit_adjust
)) & 0x1;
if(dimm_config
& DIMM_1G
) // 1G or 2G
if(dimm_config
& DIMM_CONF_8
)
cs
= ((saddr
) >> (14 - bit_adjust
)) & 0x1;
else if(dimm_config
& DIMM_CONF_6
)
cs
= ((saddr
) >> (12 - bit_adjust
)) & 0x1;
else if(dimm_config
& DIMM_CONF_4
)
cs
= ((saddr
) >> (13 - bit_adjust
)) & 0x1;
else if(dimm_config
& DIMM_CONF_2
)
cs
= ((saddr
) >> (12 - bit_adjust
)) & 0x1;
cs
= ((saddr
) >> (11 - bit_adjust
)) & 0x1;
//io_printf((char *)" cs=%d\n",cs);
int check_if_valid_PA(long long addr
, int dimm_config
, int shift
)
if(dimm_config
& DIMM_CONF_8
)
else if(dimm_config
& DIMM_CONF_4
)
else if(dimm_config
& DIMM_CONF_2
)
//if(dimm_config & RANK_LOW)
if(dimm_config
& STACK_DIMM
)
if(dimm_config
& SNG_CHANNEL
)
if(dimm_config
& DIMM_1G
)
if(dimm_config
& DIMM_512
)
else if(dimm_config
& DIMM_512
)
pa_mask_l
= (0xffffffffff >> (1 + channel_adjust
+ side_adjust
+ size_adjust
+ rank_adjust
+ dimm_adjust
));
if(addr
& (~pa_mask_l
)) {
io_printf((char *)"Warning: Out-of-bound address detected. Address is %llx\n",addr
);