summaryrefslogtreecommitdiffstats
path: root/src/usr/scom/scom.C
diff options
context:
space:
mode:
authorMissy Connell <missyc@us.ibm.com>2011-12-06 13:06:18 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-01-24 14:43:04 -0600
commit52b60aea13ffc9a8d67a6714e1416402fd203139 (patch)
tree209e89b8fdeb35126712c2d75bb49b6eb396be36 /src/usr/scom/scom.C
parent8514ef2acf01728b5a07fbd3c94999375cc0aec6 (diff)
downloadblackbird-hostboot-52b60aea13ffc9a8d67a6714e1416402fd203139.tar.gz
blackbird-hostboot-52b60aea13ffc9a8d67a6714e1416402fd203139.zip
Indirect SCOM support
Added locking Change-Id: If2b3c2d69bb533a65cd9b41c1eaf595e979f93aa Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/562 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/scom/scom.C')
-rw-r--r--src/usr/scom/scom.C113
1 files changed, 110 insertions, 3 deletions
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C
index ed5ffb306..8bfdbf004 100644
--- a/src/usr/scom/scom.C
+++ b/src/usr/scom/scom.C
@@ -55,6 +55,8 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
TARGETING::TYPE_MEMBUF,
scomPerformOp);
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
@@ -65,6 +67,112 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
va_list i_args)
{
errlHndl_t l_err = NULL;
+ mutex_t* l_mutex = NULL;
+
+ uint64_t l_scomAddr = va_arg(i_args,uint64_t);
+
+ // If the indirect scom bit is 0, then doing a regular scom
+ if( (l_scomAddr & 0x8000000000000000) == 0)
+ {
+ l_err = doScomOp(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+ }
+ // We are performing an indirect scom.
+ else
+ {
+ uint64_t l_io_buffer;
+ uint64_t temp_scomAddr;
+
+ memcpy(&l_io_buffer, io_buffer, 8);
+ memcpy(&temp_scomAddr, &l_scomAddr, 8);
+
+ // Get the 20bit indirect scom address
+ temp_scomAddr = temp_scomAddr & 0x001FFFFF00000000;
+
+ // Zero out the indirect address location.. leave the 16bits of data
+ l_io_buffer = l_io_buffer & 0x000000000000FFFF;
+
+ // OR in the 20bit indirect address
+ l_io_buffer = l_io_buffer | temp_scomAddr;
+
+ // zero out the indirect address from the buffer..
+ l_scomAddr = l_scomAddr & 0x00000000EFFFFFFFF;
+
+ // If we are doing a read. We need to do a write first..
+ if(i_opType == DeviceFW::READ)
+ {
+
+ // use the chip-specific mutex attribute
+ l_mutex = i_target->getHbMutexAttr<TARGETING::ATTR_SCOM_IND_MUTEX>();
+
+ mutex_lock(l_mutex);
+
+ // turn the read bit on.
+ l_io_buffer = l_io_buffer | 0x8000000000000000;
+
+ // perform write before the read with the new
+ // IO_buffer with the imbedded indirect scom addr.
+ l_err = doScomOp(DeviceFW::WRITE,
+ i_target,
+ & l_io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+
+ if (l_err != NULL)
+ {
+ mutex_unlock(l_mutex);
+ return l_err;
+ }
+
+ // Now perform the op requested using the passed in
+ // IO_Buffer to pass the read data back to caller.
+ l_err = doScomOp(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+
+ mutex_unlock(l_mutex);
+
+ }
+ else //write
+ {
+
+ // Turn the read bit off.
+ l_io_buffer = l_io_buffer & 0x7FFFFFFFFFFFFFFF;
+
+ // Now perform the op requested using the
+ // locai io_buffer with the indirect addr imbedded.
+ l_err = doScomOp(i_opType,
+ i_target,
+ & l_io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+ }
+ }
+
+ return l_err;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t doScomOp(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr)
+{
+
+ errlHndl_t l_err = NULL;
do{
//Always XSCOM the Master Sentinel
@@ -76,7 +184,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
i_target,
io_buffer,
io_buflen,
- DEVICE_XSCOM_ADDRESS(va_arg(i_args,uint64_t)));
+ DEVICE_XSCOM_ADDRESS(i_addr));
break;
}
else if(i_target->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom)
@@ -85,7 +193,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
i_target,
io_buffer,
io_buflen,
- DEVICE_FSISCOM_ADDRESS(va_arg(i_args,uint64_t)));
+ DEVICE_FSISCOM_ADDRESS(i_addr));
if( l_err ) { break; }
}
else
@@ -101,5 +209,4 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
}
-
} // end namespace
OpenPOWER on IntegriCloud