1 /** 2 * Copyright © 2017 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <endian.h> 18 #include <experimental/filesystem> 19 #include <phosphor-logging/log.hpp> 20 #include <regex> 21 #include "targeting.hpp" 22 23 namespace openpower 24 { 25 namespace targeting 26 { 27 28 using namespace phosphor::logging; 29 namespace fs = std::experimental::filesystem; 30 31 int Target::getCFAMFD() 32 { 33 if (cfamFD.get() == nullptr) 34 { 35 cfamFD = std::make_unique< 36 openpower::util::FileDescriptor>(getCFAMPath()); 37 } 38 39 return cfamFD->get(); 40 } 41 42 std::unique_ptr<Target>& Targeting::getTarget(size_t pos) 43 { 44 auto search = [pos](const auto& t) 45 { 46 return t->getPos() == pos; 47 }; 48 49 auto target = find_if(targets.begin(), targets.end(), search); 50 if (target == targets.end()) 51 { 52 throw std::runtime_error("Target not found: " + std::to_string(pos)); 53 } 54 else 55 { 56 return *target; 57 } 58 } 59 60 61 static uint32_t noEndianSwap(uint32_t data) 62 { 63 return data; 64 } 65 66 static uint32_t endianSwap(uint32_t data) 67 { 68 return htobe32(data); 69 } 70 71 Targeting::Targeting(const std::string& fsiMasterDev, 72 const std::string& fsiSlaveDir) : 73 fsiMasterPath(fsiMasterDev), 74 fsiSlaveBasePath(fsiSlaveDir) 75 { 76 swap_endian_t swapper = endianSwap; 77 std::regex exp{"fsi1/slave@([0-9]{2}):00", std::regex::extended}; 78 79 if (!fs::exists(fsiMasterPath)) 80 { 81 std::regex expOld{"hub@00/slave@([0-9]{2}):00", std::regex::extended}; 82 83 //Fall back to old (4.7) path 84 exp = expOld; 85 fsiMasterPath = fsiMasterDevPathOld; 86 fsiSlaveBasePath = fsiSlaveBaseDirOld; 87 88 //And don't swap the endianness of CFAM data 89 swapper = noEndianSwap; 90 } 91 92 //Always create P0, the FSI master. 93 targets.push_back(std::make_unique<Target>(0, fsiMasterPath, swapper)); 94 95 //Find the the remaining P9s dynamically based on which files show up 96 for (auto& file : fs::directory_iterator(fsiSlaveBasePath)) 97 { 98 std::smatch match; 99 std::string path = file.path(); 100 if (std::regex_search(path, match, exp)) 101 { 102 auto pos = atoi(match[1].str().c_str()); 103 if (pos == 0) 104 { 105 log<level::ERR>("Unexpected FSI slave device name found", 106 entry("DEVICE_NAME=%s", path.c_str())); 107 continue; 108 } 109 110 path += "/raw"; 111 112 targets.push_back(std::make_unique<Target>(pos, path, swapper)); 113 } 114 } 115 116 auto sortTargets = [](const std::unique_ptr<Target>& left, 117 const std::unique_ptr<Target>& right) 118 { 119 return left->getPos() < right->getPos(); 120 }; 121 std::sort(targets.begin(), targets.end(), sortTargets); 122 } 123 124 } 125 } 126