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 #include <unistd.h> 17 #include "cfam_access.hpp" 18 #include "targeting.hpp" 19 20 namespace openpower 21 { 22 namespace cfam 23 { 24 namespace access 25 { 26 27 constexpr auto cfamRegSize = 4; 28 29 using namespace openpower::targeting; 30 using namespace openpower::util; 31 32 /** 33 * Converts the CFAM register address used by the calling 34 * code (because that's how it is in the spec) to the address 35 * required by the device driver. 36 */ 37 static inline cfam_address_t makeOffset(cfam_address_t address) 38 { 39 return (address & 0xFC00) | ((address & 0x03FF) << 2); 40 } 41 42 43 void writeReg(const std::unique_ptr<Target>& target, 44 cfam_address_t address, 45 cfam_data_t data) 46 { 47 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET); 48 if (rc < 0) 49 { 50 //Future: use a different exception to create an error log 51 char msg[100]; 52 sprintf(msg, "writeCFAMReg: Failed seek for address 0x%X, " 53 "processor %d. errno = %d", 54 address, target->getPos(), errno); 55 throw std::runtime_error(msg); 56 } 57 58 rc = write(target->getCFAMFD(), &data, cfamRegSize); 59 if (rc < 0) 60 { 61 //Future: use a different exception to create an error log 62 char msg[100]; 63 sprintf(msg, "writeCFAMReg: Failed write to address 0x%X, " 64 "processor %d. errno = %d", 65 address, target->getPos(), errno); 66 throw std::runtime_error(msg); 67 } 68 } 69 70 71 cfam_data_t readReg(const std::unique_ptr<Target>& target, 72 cfam_address_t address) 73 { 74 cfam_data_t data = 0; 75 76 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET); 77 if (rc < 0) 78 { 79 //Future: use a different exception to create an error log 80 char msg[100]; 81 sprintf(msg, "readCFAMReg: Failed seek for address 0x%X, " 82 "processor %d. errno = %d", 83 address, target->getPos(), errno); 84 throw std::runtime_error(msg); 85 } 86 87 rc = read(target->getCFAMFD(), &data, cfamRegSize); 88 if (rc < 0) 89 { 90 //Future: use a different exception to create an error log 91 char msg[100]; 92 sprintf(msg, "readCFAMReg: Failed read for address 0x%X, " 93 "processor %d. errno = %d", 94 address, target->getPos(), errno); 95 throw std::runtime_error(msg); 96 } 97 98 return data; 99 } 100 101 102 void writeRegWithMask(const std::unique_ptr<Target>& target, 103 cfam_address_t address, 104 cfam_data_t data, 105 cfam_mask_t mask) 106 { 107 cfam_data_t readData = readReg(target, address); 108 109 readData &= ~mask; 110 readData |= (data & mask); 111 112 writeReg(target, address, readData); 113 } 114 115 } 116 } 117 } 118