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