// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: sas_cnfg.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named 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 work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
* "sas_cnfg.cc" LSI SAS1064E PCIE to 4-Port Serial Attached
* SCSI Controller Simulator
* SAS controller configuration
* Copyright (C) 2007 Sun Microsystems, Inc.
// 64-bit base SAS address, each port will be assigned
// a consecutive value starting from this one.
#define SAS_ADDRESS_LOW 0x12345678
#define SAS_ADDRESS_HIGH 0x9abcdef0
// device handle for the controller
#define CNTL_DEV_HANDLE 0x1000
// device handles for devices attached to ports
#define CHILD_DEV0_HANDLE 0x1001
#define CHILD_DEV1_HANDLE (CHILD_DEV0_HANDLE + 1)
#define CHILD_DEV2_HANDLE (CHILD_DEV0_HANDLE + 2)
#define CHILD_DEV3_HANDLE (CHILD_DEV0_HANDLE + 3)
static config_page_header_t manufacturing_page_headers
[8] = {
static config_page_manufacturing_5_t config_page_manufacturing_5
= {
static config_page_header_t ioc_page_headers
[7] = {
static config_page_ioc_1_t config_page_ioc_1
= {
static config_page_ioc_2_t config_page_ioc_2
= {
static config_extended_page_header sas_io_unit_page_headers
[2] = {
{1, 0, 0, 0x3f, 20, 0x10, 0},
{1, 0, 1, 0x3f, 17, 0x10, 0},
static config_page_sas_io_unit_0_t config_page_sas_io_unit_0
= {
{1, 0, 0, 0x3f, 20, 0x10, 0},
{0, 0, 0, 0, 0x1c01, CHILD_DEV0_HANDLE
, CNTL_DEV_HANDLE
, 0},
static config_extended_page_header sas_device_page_headers
[2] = {
{1, 0, 0, 0x3f, 9, 0x12, 0},
{1, 0, 1, 0x3f, 12, 0x12, 0},
static config_page_sas_device_0_t config_page_sas_device_0
= {
{1, 0, 0, 0x3f, 9, 0x12, 0},
static config_extended_page_header sas_phy_page_headers
[2] = {
{1, 0, 0, 0x3f, 9, 0x13, 0},
{1, 0, 1, 0x3f, 7, 0x13, 0},
static config_page_sas_phy_0_t config_page_sas_phy_0
= {
{1, 0, 0, 0x3f, 9, 0x13, 0},
0x11, // attached phy identifier
0x0909, // programmed link rate
void SAS::send_page_reply(msg_config_t
*req
, msg_config_reply_t
*reply
, config_page_header_t
*page_header
) {
reply
->Action
= req
->Action
;
reply
->MsgLength
= sizeof(msg_config_reply_t
) >> 2;
reply
->Function
= req
->Function
;
reply
->ExtPageLength
= 0;
reply
->MsgContext
= req
->MsgContext
;
reply
->IOCStatus
= SAM_LE_16(MPI_IOCSTATUS_SUCCESS
);
reply
->Header
.PageVersion
= page_header
->PageVersion
;
reply
->Header
.PageLength
= page_header
->PageLength
;
reply
->Header
.PageNumber
= page_header
->PageNumber
;
reply
->Header
.PageType
= page_header
->PageType
;
void SAS::send_extended_page_reply(msg_config_t
*req
, msg_config_reply_t
*reply
,
config_extended_page_header
*extended_page_header
, bool invalid
) {
reply
->Action
= req
->Action
;
reply
->MsgLength
= sizeof(msg_config_reply_t
) >> 2;
reply
->Function
= req
->Function
;
reply
->ExtPageLength
= SAM_LE_16(extended_page_header
->ExtPageLength
);
reply
->ExtPageType
= extended_page_header
->ExtPageType
;
reply
->MsgContext
= req
->MsgContext
;
reply
->IOCStatus
= SAM_LE_16(invalid
? MPI_IOCSTATUS_CONFIG_INVALID_PAGE
: MPI_IOCSTATUS_SUCCESS
);
reply
->Header
.PageVersion
= extended_page_header
->PageVersion
;
reply
->Header
.PageLength
= 0;
reply
->Header
.PageNumber
= extended_page_header
->PageNumber
;
reply
->Header
.PageType
= extended_page_header
->PageType
;
// Access manufacturing pages
void SAS::access_page_manufacturing(msg_config_t
*req
, msg_config_reply_t
*reply
) {
config_page_manufacturing_5_t
*page_5
;
uint8_t page_no
= req
->Header
.PageNumber
;
uint8_t sge_flags
= req
->PageBufferSGE
.u1
.Simple
.FlagsLength
>> MPI_SGE_FLAGS_SHIFT
;
case MPI_CONFIG_ACTION_PAGE_HEADER
:
send_page_reply(req
, reply
, &manufacturing_page_headers
[page_no
]);
case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
:
debug_err("%s: manufacturing page write is not support yet\n", getName());
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM
:
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
// allocate space for page
page_5
= (config_page_manufacturing_5_t
*)calloc(1, sizeof(config_page_manufacturing_5_t
));
bcopy(&config_page_manufacturing_5
, page_5
, sizeof(config_page_manufacturing_5_t
));
page_5
->BaseWWID_L
= SAM_LE_32(page_5
->BaseWWID_L
);
page_5
->BaseWWID_H
= SAM_LE_32(page_5
->BaseWWID_H
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_5
,
sizeof(config_page_manufacturing_5_t
), true);
send_page_reply(req
, reply
, &manufacturing_page_headers
[page_no
]);
debug_err("%s: manufacturing page read is not supported yet\n", getName());
debug_err("%s: page buffer SGE is not simple element\n", getName());
case MPI_CONFIG_ACTION_PAGE_DEFAULT
:
case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT
:
debug_err("%s: manufacturing page default is not supported yet\n", getName());
debug_err("%s: unknown page configuration action\n", getName());
void SAS::access_page_ioc(msg_config_t
*req
, msg_config_reply_t
*reply
) {
config_page_ioc_1_t
*page_1
;
config_page_ioc_2_t
*page_2
;
uint8_t page_no
= req
->Header
.PageNumber
;
uint8_t sge_flags
= req
->PageBufferSGE
.u1
.Simple
.FlagsLength
>> MPI_SGE_FLAGS_SHIFT
;
case MPI_CONFIG_ACTION_PAGE_HEADER
:
send_page_reply(req
, reply
, &ioc_page_headers
[page_no
]);
case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
:
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
// allocate space for page
page_1
= (config_page_ioc_1_t
*)calloc(1, sizeof(config_page_ioc_1_t
));
// move the page from the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_1
,
sizeof(config_page_ioc_1_t
), false);
page_1
->Flags
= SAM_LE_32(page_1
->Flags
);
page_1
->CoalescingTimeout
= SAM_LE_32(page_1
->CoalescingTimeout
);
bcopy(page_1
, &config_page_ioc_1
, sizeof(config_page_ioc_1_t
));
send_page_reply(req
, reply
, &ioc_page_headers
[page_no
]);
debug_err("%s: ioc pages write is not supported yet\n", getName());
debug_err("%s: page buffer SGE is not simple element\n", getName());
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM
:
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
// allocate space for page
page_1
= (config_page_ioc_1_t
*)calloc(1, sizeof(config_page_ioc_1_t
));
bcopy(&config_page_ioc_1
, page_1
, sizeof(config_page_ioc_1_t
));
page_1
->Flags
= SAM_LE_32(page_1
->Flags
);
page_1
->CoalescingTimeout
= SAM_LE_32(page_1
->CoalescingTimeout
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_1
,
sizeof(config_page_ioc_1_t
), true);
send_page_reply(req
, reply
, &ioc_page_headers
[page_no
]);
// allocate space for page
page_2
= (config_page_ioc_2_t
*)calloc(1, sizeof(config_page_ioc_2_t
));
bcopy(&config_page_ioc_2
, page_2
, sizeof(config_page_ioc_2_t
));
page_2
->CapabilitiesFlags
= SAM_LE_32(page_2
->CapabilitiesFlags
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_2
,
sizeof(config_page_ioc_2_t
), true);
send_page_reply(req
, reply
, &ioc_page_headers
[page_no
]);
debug_err("%s: ioc page read is not supported yet\n", getName());
debug_err("%s: page buffer SGE is not simple element\n", getName());
case MPI_CONFIG_ACTION_PAGE_DEFAULT
:
case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT
:
debug_err("%s: ioc page default is not supported yet\n", getName());
debug_err("%s: unknown page configuration action\n", getName());
// Access sas io unit page
void SAS::access_page_sas_io_unit(msg_config_t
*req
, msg_config_reply_t
*reply
) {
config_page_sas_io_unit_0_t
*page_0
;
uint8_t page_no
= req
->Header
.PageNumber
;
uint8_t sge_flags
= req
->PageBufferSGE
.u1
.Simple
.FlagsLength
>> MPI_SGE_FLAGS_SHIFT
;
case MPI_CONFIG_ACTION_PAGE_HEADER
: {
send_extended_page_reply(req
, reply
, &sas_io_unit_page_headers
[page_no
], false);
case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
:
debug_err("%s: sas io unit page write is not support yet\n", getName());
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM
: {
// some times the driver forgets to set flag, just treat it as Simple Element
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) == 0) {
debug_info("%s: flag of page buffer SGE in IO UNIT request is 0, change it to 1\n", getName());
sge_flags
|= MPI_SGE_FLAGS_SIMPLE_ELEMENT
;
req
->PageBufferSGE
.u1
.Simple
.FlagsLength
|= (MPI_SGE_FLAGS_SIMPLE_ELEMENT
<< MPI_SGE_FLAGS_SHIFT
);
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
page_0
= (config_page_sas_io_unit_0_t
*)calloc(1, sizeof(config_page_sas_io_unit_0_t
) +
sizeof(mpi_sas_io_unit0_phy_data_t
) * 3);
bcopy(&config_page_sas_io_unit_0
, page_0
, sizeof(config_page_sas_io_unit_0_t
));
page_0
->Header
.ExtPageLength
= SAM_LE_16(page_0
->Header
.ExtPageLength
);
// construct information for all ports
for (int i
= 0; i
< IOC_NUM_PORTS
; i
++) {
bcopy(&config_page_sas_io_unit_0
.PhyData
[0],
&page_0
->PhyData
[i
], sizeof(mpi_sas_io_unit0_phy_data_t
));
page_0
->PhyData
[i
].Port
= i
;
page_0
->PhyData
[i
].AttachedDeviceHandle
= SAM_LE_16(CHILD_DEV0_HANDLE
+ i
);
page_0
->PhyData
[i
].ControllerDevHandle
= SAM_LE_16(CNTL_DEV_HANDLE
);
page_0
->PhyData
[i
].ControllerPhyDeviceInfo
=
SAM_LE_32(page_0
->PhyData
[i
].ControllerPhyDeviceInfo
& ~3);
page_0
->PhyData
[i
].ControllerPhyDeviceInfo
=
SAM_LE_32(page_0
->PhyData
[i
].ControllerPhyDeviceInfo
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_0
,
sizeof(config_page_sas_io_unit_0_t
) + sizeof(mpi_sas_io_unit0_phy_data_t
) * 3, true);
send_extended_page_reply(req
, reply
, &sas_io_unit_page_headers
[page_no
], false);
debug_err("%s: sas ioc unit page read not supported yet\n", getName());
case MPI_CONFIG_ACTION_PAGE_DEFAULT
:
case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT
:
debug_err("%s: sas io unit page default is not supported yet\n", getName());
debug_err("%s: unknown page configuration action\n", getName());
// Access sas device pages
// Page address can be one of three formats: get_next_handle, bus_target_id, and handle
void SAS::access_page_sas_device(msg_config_t
*req
, msg_config_reply_t
*reply
) {
config_page_sas_device_0_t
*page_0
;
uint8_t page_no
= req
->Header
.PageNumber
;
uint8_t sge_flags
= req
->PageBufferSGE
.u1
.Simple
.FlagsLength
>> MPI_SGE_FLAGS_SHIFT
;
switch ((req
->PageAddress
& MPI_SAS_DEVICE_PGAD_FORM_MASK
) >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT
) {
case MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
: {
handle
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK
) >> MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT
;
else if (handle
>= CHILD_DEV0_HANDLE
&& handle
< CHILD_DEV3_HANDLE
)
target
= handle
- CHILD_DEV0_HANDLE
+ 1;
for (i
= target
; i
< IOC_NUM_PORTS
; i
++)
case MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
: {
bus
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_BT_BUS_MASK
) >> MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT
;
target
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_BT_TID_MASK
) >> MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT
;
if (bus
!= 0 || target
> IOC_NUM_PORTS
)
case MPI_SAS_DEVICE_PGAD_FORM_HANDLE
: {
handle
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK
) >> MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT
;
if (handle
>= CHILD_DEV0_HANDLE
&& handle
<= CHILD_DEV3_HANDLE
)
target
= handle
- CHILD_DEV0_HANDLE
;
debug_err("%s: unknown sas device page address format\n", getName());
case MPI_CONFIG_ACTION_PAGE_HEADER
: {
send_extended_page_reply(req
, reply
, &sas_device_page_headers
[page_no
], invalid
);
case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
:
debug_err("%s: sas device page write is not support yet\n", getName());
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM
: {
send_extended_page_reply(req
, reply
, &sas_device_page_headers
[page_no
], true);
// some times the driver forgets to set flag, just treat it as Simple Element
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) == 0) {
debug_info("%s: flag of page buffer SGE in DEVICE request is 0, change it to 1\n", getName());
sge_flags
|= MPI_SGE_FLAGS_SIMPLE_ELEMENT
;
req
->PageBufferSGE
.u1
.Simple
.FlagsLength
|= (MPI_SGE_FLAGS_SIMPLE_ELEMENT
<< MPI_SGE_FLAGS_SHIFT
);
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
// allocate space for page
page_0
= (config_page_sas_device_0_t
*)calloc(1, sizeof(config_page_sas_device_0_t
));
bcopy(&config_page_sas_device_0
, page_0
, sizeof(config_page_sas_device_0_t
));
page_0
->Header
.ExtPageLength
= SAM_LE_16(page_0
->Header
.ExtPageLength
);
page_0
->SASAddress_L
= SAM_LE_32(page_0
->SASAddress_L
+ target
);
page_0
->SASAddress_H
= SAM_LE_32(page_0
->SASAddress_H
);
page_0
->DevHandle
= SAM_LE_16(page_0
->DevHandle
+ target
);
page_0
->TargetID
= target
;
page_0
->DeviceInfo
= SAM_LE_32(page_0
->DeviceInfo
);
page_0
->Flags
= SAM_LE_16(page_0
->Flags
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_0
,
sizeof(config_page_sas_device_0_t
), true);
send_extended_page_reply(req
, reply
, &sas_device_page_headers
[page_no
], false);
debug_err("%s: sas device page write read not supported yet\n", getName());
debug_err("%s: page buffer SGE is not simple element\n", getName());
case MPI_CONFIG_ACTION_PAGE_DEFAULT
:
case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT
:
debug_err("%s: sas device page default is not supported yet\n", getName());
debug_err("%s: unknown page configuration action\n", getName());
// Note: 1. it is a mistake that the driver use the same page address format as sas device pages.
// 2. sas phy pages are not used by the new version of mpt driver any more.
void SAS::access_page_sas_phy(msg_config_t
*req
, msg_config_reply_t
*reply
) {
config_page_sas_phy_0_t
*page_0
;
uint8_t page_no
= req
->Header
.PageNumber
;
uint8_t sge_flags
= req
->PageBufferSGE
.u1
.Simple
.FlagsLength
>> MPI_SGE_FLAGS_SHIFT
;
switch ((req
->PageAddress
& MPI_SAS_DEVICE_PGAD_FORM_MASK
) >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT
) {
case MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
: {
phynum
= (req
->PageAddress
& MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK
) >> MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT
;
if (phynum
>= 0 && phynum
< IOC_NUM_PORTS
)
case MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
: {
bus
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_BT_BUS_MASK
) >> MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT
;
target
= (req
->PageAddress
& MPI_SAS_DEVICE_PGAD_BT_TID_MASK
) >> MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT
;
if (bus
!= 0 || target
> IOC_NUM_PORTS
)
debug_err("%s: unknown sas phy page address format\n", getName());
case MPI_CONFIG_ACTION_PAGE_HEADER
:
send_extended_page_reply(req
, reply
, &sas_phy_page_headers
[page_no
], invalid
);
case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM
:
debug_err("%s: sas phy page write is not support yet\n", getName());
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT
:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM
: {
// some times the driver forgot to set flag, just treat it as Simple Element
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) == 0) {
debug_info("%s: flag of page buffer SGE in PHY request is 0, change it to 1\n", getName());
sge_flags
|= MPI_SGE_FLAGS_SIMPLE_ELEMENT
;
req
->PageBufferSGE
.u1
.Simple
.FlagsLength
|= (MPI_SGE_FLAGS_SIMPLE_ELEMENT
<< MPI_SGE_FLAGS_SHIFT
);
if ((sge_flags
& MPI_SGE_FLAGS_ELEMENT_TYPE_MASK
) ==
MPI_SGE_FLAGS_SIMPLE_ELEMENT
) {
// even for invalid target, page is still moved to the main memory,
// but with some fields set to invalid.
// allocate space for page
page_0
= (config_page_sas_phy_0_t
*)calloc(1, sizeof(config_page_sas_phy_0_t
));
bcopy(&config_page_sas_phy_0
, page_0
, sizeof(config_page_sas_phy_0_t
));
page_0
->Header
.ExtPageLength
= SAM_LE_16(page_0
->Header
.ExtPageLength
);
page_0
->SASAddress_L
= SAM_LE_32(invalid
? 0 : page_0
->SASAddress_L
+ target
);
page_0
->SASAddress_H
= SAM_LE_32(invalid
? 0 : page_0
->SASAddress_H
);
page_0
->AttachedDevHandle
= SAM_LE_16(invalid
? 0 : page_0
->AttachedDevHandle
+ target
);
page_0
->AttachedDeviceInfo
= SAM_LE_32(invalid
? 0 : page_0
->AttachedDeviceInfo
);
page_0
->PhyInfo
= SAM_LE_32(page_0
->PhyInfo
);
// move the page to the main memory
memory_transport((void *)&(req
->PageBufferSGE
), (void*)page_0
,
sizeof(config_page_sas_phy_0_t
), true);
send_extended_page_reply(req
, reply
, &sas_phy_page_headers
[page_no
], invalid
);
debug_err("%s: sas phy page read is not supported yet\n", getName());
debug_err("%s: page buffer SGE is not simple element\n", getName());
case MPI_CONFIG_ACTION_PAGE_DEFAULT
:
case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT
:
debug_err("%s: sas phy page default is not supported yet\n", getName());
debug_err("%s: unknown page configuration action\n", getName());