Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / sas / sas_cnfg.cc
// ========== 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.
* All rights reserved.
*
*/
#include "sas.h"
// 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)
// manufacturing pages
static config_page_header_t manufacturing_page_headers[8] = {
{1, 19, 0, 0x39},
{1, 65, 1, 0x39},
{1, 3, 2, 0x39},
{1, 3, 3, 0x39},
{1, 21, 4, 0x39},
{1, 3, 5, 0x39},
{1, 2, 6, 0x39},
{1, 15, 7, 0x39},
};
static config_page_manufacturing_5_t config_page_manufacturing_5 = {
{1, 3, 5, 0x39},
SAS_ADDRESS_LOW,
SAS_ADDRESS_HIGH,
};
// ioc pages
static config_page_header_t ioc_page_headers[7] = {
{1, 7, 0, 0x31},
{1, 4, 1, 0x21},
{1, 5, 2, 0x31},
{1, 3, 3, 0x31},
{1, 3, 4, 0x21},
{1, 4, 5, 0x31},
{1, 15, 6, 0x31},
};
static config_page_ioc_1_t config_page_ioc_1 = {
{1, 4, 1, 0x21},
0, 0, 0, 1,
{0, 0},
};
static config_page_ioc_2_t config_page_ioc_2 = {
{1, 5, 2, 0x31},
0, 0, 0, 0, 0,
{0, 0, 0, 0, 0, 0, 0},
};
// SAS io unit pages
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, 4, 0, 0,
{0, 0, 0, 0, 0x1c01, CHILD_DEV0_HANDLE, CNTL_DEV_HANDLE, 0},
};
// SAS device pages
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},
0,
SAS_ADDRESS_LOW,
SAS_ADDRESS_HIGH,
0,
CHILD_DEV0_HANDLE,
0, 0, // target, bus
0x1c01, // device info
0x7, // flags
0, // physical port
0,
};
// SAS phy pages
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},
0,
SAS_ADDRESS_LOW,
SAS_ADDRESS_HIGH,
CHILD_DEV0_HANDLE,
0x11, // attached phy identifier
0,
0x1c01, // device info
0x0909, // programmed link rate
0x0909, // hw link rate
0, // change count
0,
0x0909, // phy info
};
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->ExtPageType = 0;
reply->MsgFlags = 0;
reply->MsgContext = req->MsgContext;
reply->IOCStatus = SAM_LE_16(MPI_IOCSTATUS_SUCCESS);
reply->IOCLogInfo = 0;
reply->Header.PageVersion = page_header->PageVersion;
reply->Header.PageLength = page_header->PageLength;
reply->Header.PageNumber = page_header->PageNumber;
reply->Header.PageType = page_header->PageType;
send_handshake_msg();
}
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->MsgFlags = 0;
reply->MsgContext = req->MsgContext;
reply->IOCStatus = SAM_LE_16(invalid ? MPI_IOCSTATUS_CONFIG_INVALID_PAGE : MPI_IOCSTATUS_SUCCESS);
reply->IOCLogInfo = 0;
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;
send_handshake_msg();
}
// 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;
switch (req->Action) {
case MPI_CONFIG_ACTION_PAGE_HEADER:
send_page_reply(req, reply, &manufacturing_page_headers[page_no]);
break;
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());
exit(1);
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) {
if (page_no == 5) {
// 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);
// reply message
send_page_reply(req, reply, &manufacturing_page_headers[page_no]);
free(page_5);
}
else {
debug_err("%s: manufacturing page read is not supported yet\n", getName());
exit(1);
}
}
else {
debug_err("%s: page buffer SGE is not simple element\n", getName());
exit(1);
}
break;
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());
exit(1);
default:
debug_err("%s: unknown page configuration action\n", getName());
exit(1);
}
return;
}
// Access ioc pages
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;
switch (req->Action) {
case MPI_CONFIG_ACTION_PAGE_HEADER:
send_page_reply(req, reply, &ioc_page_headers[page_no]);
break;
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) {
if (page_no == 1) {
// 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));
// reply message
send_page_reply(req, reply, &ioc_page_headers[page_no]);
free(page_1);
}
else {
debug_err("%s: ioc pages write is not supported yet\n", getName());
exit(1);
}
}
else {
debug_err("%s: page buffer SGE is not simple element\n", getName());
exit(1);
}
break;
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) {
switch (page_no) {
case 1:
// 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);
// reply message
send_page_reply(req, reply, &ioc_page_headers[page_no]);
free(page_1);
break;
case 2:
// 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);
// reply message
send_page_reply(req, reply, &ioc_page_headers[page_no]);
free(page_2);
break;
default:
debug_err("%s: ioc page read is not supported yet\n", getName());
exit(1);
}
}
else {
debug_err("%s: page buffer SGE is not simple element\n", getName());
exit(1);
}
break;
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());
exit(1);
default:
debug_err("%s: unknown page configuration action\n", getName());
exit(1);
}
return;
}
// 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;
switch (req->Action) {
case MPI_CONFIG_ACTION_PAGE_HEADER: {
send_extended_page_reply(req, reply, &sas_io_unit_page_headers[page_no], false);
break;
}
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());
exit(1);
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) {
if (page_no == 0) {
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);
if (_disk[i] == NULL)
page_0->PhyData[i].ControllerPhyDeviceInfo =
SAM_LE_32(page_0->PhyData[i].ControllerPhyDeviceInfo & ~3);
else
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);
// reply message
send_extended_page_reply(req, reply, &sas_io_unit_page_headers[page_no], false);
free(page_0);
}
else {
debug_err("%s: sas ioc unit page read not supported yet\n", getName());
exit(1);
}
}
break;
}
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());
exit(1);
default:
debug_err("%s: unknown page configuration action\n", getName());
exit(1);
}
}
// 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;
uint16_t handle;
uint8_t bus, target;
bool invalid = false;
// find the target
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;
if (handle == 0xffff)
target = 0;
else if (handle >= CHILD_DEV0_HANDLE && handle < CHILD_DEV3_HANDLE)
target = handle - CHILD_DEV0_HANDLE + 1;
else
invalid = true;
if (!invalid) {
int i;
for (i = target; i < IOC_NUM_PORTS; i++)
if (_disk[i])
break;
if (i < IOC_NUM_PORTS)
target = i;
else
invalid = true;
}
break;
}
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)
invalid = true;
if (!invalid)
if (!_disk[target])
invalid = true;
break;
}
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;
else
invalid = true;
if (!invalid)
if (!_disk[target])
invalid = true;
break;
}
default:
debug_err("%s: unknown sas device page address format\n", getName());
exit(1);
}
switch (req->Action) {
case MPI_CONFIG_ACTION_PAGE_HEADER: {
send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], invalid);
break;
}
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());
exit(1);
case MPI_CONFIG_ACTION_PAGE_READ_CURRENT:
case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: {
if (invalid) {
send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], true);
}
else {
// 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) {
if (page_no == 0) {
// 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->Bus = 0;
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);
// reply message
send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], false);
free(page_0);
}
else {
debug_err("%s: sas device page write read not supported yet\n", getName());
exit(1);
}
}
else {
debug_err("%s: page buffer SGE is not simple element\n", getName());
exit(1);
}
}
break;
}
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());
exit(1);
default:
debug_err("%s: unknown page configuration action\n", getName());
exit(1);
}
return;
}
// Access sas phy pages
// 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;
uint16_t phynum;
uint8_t bus, target;
bool invalid = false;
// find the target
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)
target = phynum;
else
invalid = true;
if (!invalid) {
if (!_disk[target])
invalid = true;
}
break;
}
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)
invalid = true;
if (!invalid)
if (!_disk[target])
invalid = true;
break;
}
default:
debug_err("%s: unknown sas phy page address format\n", getName());
exit(1);
}
switch (req->Action) {
case MPI_CONFIG_ACTION_PAGE_HEADER:
send_extended_page_reply(req, reply, &sas_phy_page_headers[page_no], invalid);
break;
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());
exit(1);
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.
if (page_no == 0) {
// 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);
// reply message
send_extended_page_reply(req, reply, &sas_phy_page_headers[page_no], invalid);
free(page_0);
}
else {
debug_err("%s: sas phy page read is not supported yet\n", getName());
exit(1);
}
}
else {
debug_err("%s: page buffer SGE is not simple element\n", getName());
exit(1);
}
break;
}
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());
exit(1);
default:
debug_err("%s: unknown page configuration action\n", getName());
exit(1);
}
return;
}