diff options
| author | Missy Connell <missyc@us.ibm.com> | 2011-12-06 13:06:18 -0600 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-01-24 14:43:04 -0600 |
| commit | 52b60aea13ffc9a8d67a6714e1416402fd203139 (patch) | |
| tree | 209e89b8fdeb35126712c2d75bb49b6eb396be36 /src/usr/scom/scom.C | |
| parent | 8514ef2acf01728b5a07fbd3c94999375cc0aec6 (diff) | |
| download | blackbird-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.C | 113 |
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 |

