Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / include / pci_common.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: pci_common.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23#ifndef __PCI_COMMON_H__
24#define __PCI_COMMON_H__
25
26#include <map>
27#include <stdio.h>
28#include <stdarg.h>
29
30#include "pci.h"
31
32using namespace std;
33
34class pciConfReg{
35public:
36
37 int debug_level;
38 char * name;
39 uint16_t size; //size of the register
40 void * data; //pointer to device. to be
41 //used by devices providing
42 //custom read/write for nonstandard conf regs,
43 //unimplemented, reserved reg etc
44
45 bool isHole; //true for unimplemented registers
46
47 pciConfReg(uint16_t sz = 0x100){
48 name = new char[1];
49 *name = '\0';
50 size = sz;
51 val = 0;
52 mask = 0;
53 isHole = true;
54 data = 0;
55 debug_level = 0;
56 }
57 // args (reg name, reg size, por value, write mask, impl. specific data)
58 pciConfReg(const char * n,uint16_t sz, uint32_t v, uint32_t m ,void * d = 0){
59 name = new char[strlen(n)+1];
60 strcpy(name,n);
61 size = sz;
62 val = v;
63 mask = m;
64 data = d;
65 isHole = false;
66 debug_level = 0;
67 }
68
69 void setDebug(int level){ debug_level = level; }
70
71// devices with different read/write accesses (eg rw1c) should override
72// these functions to provide custom behaviour and to implement device
73// specific side effects
74
75// read 'bytes_to_read/write' bytes starting from 'byte_offset'.
76// if the 'size' of register is less than bytes_to_read/write then
77// read/write the whole register. return the number
78// of bytes read/written.
79 virtual uint8_t read(uint32_t *buf, uint8_t bytes_to_read, uint8_t byte_offset = 0,uint8_t buf_offset = 0){
80 // return the bytes in buf. 'bytes_to_read' bytes are filled in from (char*)buf + buf_offset
81 // w/0 affecting the other bytes in *buf.
82 uint8_t bytes_read = (size - byte_offset) >= bytes_to_read ? bytes_to_read: size - byte_offset;
83 uint64_t byte_mask = (~ ((uint64_t) -1 << bytes_read * 8));//eg for bytes_read=1, mask = 0xff
84 *buf = (*buf & ~(byte_mask << buf_offset * 8)) | (val >> byte_offset * 8 & byte_mask) << buf_offset * 8;
85
86 if(debug_level >= 2)
87 print();
88
89 return bytes_read;
90 }
91
92 virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write){
93 uint32_t oldval = val;
94 uint8_t bytes_written = (size - byte_offset) >= bytes_to_write ? bytes_to_write:size - byte_offset;
95 uint64_t byte_mask = ~((uint64_t) -1 << bytes_written * 8);
96 //reset the writable bits in 'val' to 0, in the range
97 //val |= val & ~mask & (byte_mask << byte_offset);
98 val = val & ~(mask & (byte_mask << byte_offset));
99 val |= ((buf & byte_mask) << byte_offset * 8) & mask;
100
101 if(debug_level >= 2){
102 if(!isHole)
103 printf("Name<%s>,size<0x%x>mask<0x%lx>value<0x%lx -> 0x%lx>\n",name,size,mask,oldval,val);
104 else
105 printf("Hole: size<0x%x>\n",size);
106 }
107 return bytes_written;
108 }
109
110 virtual void setMask(uint32_t m){mask = m;}
111 virtual uint32_t getMask(){ return mask;}
112 virtual void setVal(uint32_t v){val = v;}
113
114 virtual void print(){
115 if(!isHole)
116 printf("Name<%s>,size<0x%x>value<0x%lx>,mask<0x%lx>\n",name,size,val,mask);
117 else
118 printf("Hole: size<0x%x>\n",size);
119 return;
120 }
121
122 inline bool isRO(){
123 return (mask == 0) ? true: false;
124 }
125 inline uint32_t getVal(){
126 return val;
127 }
128
129protected:
130
131 uint32_t val; //value.
132 uint32_t mask; //mask for s/w access
133
134public:
135 // set bit to either 0 or 1, taking into account the s/w mask
136 virtual bool setBit(uint8_t bit_pos, uint8_t buf){
137 val |= val & ~mask & 1 << bit_pos;
138 val |= mask & buf << bit_pos;
139 return true;
140 }
141
142 // set the bit to 1 irrespective of s/w mask.
143 // to be used by device models when acting from the h/w side
144 virtual void setBit(uint8_t bit_pos){
145 val |= (uint32_t)1 << bit_pos;
146 }
147 // reset a bit to 0, overriding the mask
148 virtual void resetBit(uint8_t bit_pos){
149 val &= ~((uint32_t)1 << bit_pos);
150 }
151
152 virtual bool getBit(uint8_t bit_pos, uint8_t *buf){
153 *buf = val >> bit_pos & 0x1;
154 return true;
155 }
156 virtual uint8_t getBit(uint8_t bit_pos){
157 return val >> bit_pos & 0x1;
158 }
159
160 // set some bit range, overriding the s/w mask
161 virtual bool setRange(uint8_t left_bit_pos, uint8_t right_bit_pos,uint32_t buf){
162
163 //bits counted from left to right
164
165 uint32_t bit_mask = ((uint32_t)-1 << left_bit_pos + 1) ^ ((uint32_t)-1 << right_bit_pos);
166 val |= val & bit_mask; //reset the bits to 0
167 val |= ((buf) << right_bit_pos) & bit_mask;//fill in the bit field
168 return true;
169 }
170 virtual bool getRange(uint8_t left_bit_pos, uint8_t right_bit_pos,uint32_t *buf){
171
172 uint32_t bit_mask = (uint32_t)-1 << left_bit_pos ^ (uint32_t)-1 << right_bit_pos;
173 *buf = val >> left_bit_pos & bit_mask;
174 return true;
175 }
176
177};
178
179
180
181
182class pciConfSpace{
183public:
184
185 //comparison function (reverse than normal default case)
186 class compare{
187 public:
188 bool operator()(int key1, int key2)const{
189 return key1 > key2;
190 }
191 };
192
193
194
195private:
196 map<int,pciConfReg *,compare> pciConfRegMap; //key is the offset of the register into the conf space
197 map<int,pciConfReg *,compare>::iterator pciConfIter;
198 typedef map<int,pciConfReg *,compare>::iterator iter_t;
199 int debug_level;
200 void initConf(confHeaderType);
201
202public:
203 bool addConfReg(pciConfReg * cr, int offset);
204 bool deleteConfReg(int offset);
205 bool confAccessSize(int offset,bool wr, uint64_t * buf,uint8_t size);
206 bool pciConfSpace::confAccessByteE(int offset,bool wr, uint64_t * in_buf,uint8_t be);
207 inline bool setMask(int offset, uint32_t mask);
208 inline bool setVal(int offset, uint32_t value);
209
210 // return pointer to the configuration register. useful for direct access
211 // functions like setBit() etc
212 pciConfReg *getConfReg(int offset){
213
214 iter_t iter = pciConfRegMap.find(offset);
215 if(iter == pciConfRegMap.end())
216 return 0;
217 else if(iter->second->isHole)
218 return 0;
219 else
220 return iter->second;
221
222 }
223
224 uint32_t readConf(int offset){
225 uint32_t retval = 0;
226 pciConfReg * reg = getConfReg(offset);
227 if(reg)
228 retval = reg->getVal();
229 //else
230 // retval = -1;
231 return retval;
232 }
233
234 pciConfSpace(confHeaderType htype = pciHeader0){
235 pciConfRegMap[0] = new pciConfReg();
236 initConf(htype);
237 debug_level = 0;
238 }
239
240 // pcie conf reg map = 0x1000
241 pciConfSpace(int size = 0x100){
242 pciConfRegMap[0] = new pciConfReg(size);
243 debug_level = 0;
244 }
245
246 void print(){
247 for(pciConfIter = pciConfRegMap.begin(); pciConfIter != pciConfRegMap.end(); pciConfIter++){
248 printf("offset:%x:",pciConfIter->first);pciConfIter->second->print();
249 }
250
251 }
252 void set_debug_level(int level){
253 debug_level = level;
254 for(pciConfIter = pciConfRegMap.begin(); pciConfIter != pciConfRegMap.end(); pciConfIter++)
255 pciConfIter->second->setDebug(level);
256 }
257};
258
259#define Here _Here(__FILE__, __LINE__)
260
261class pciDebug{
262 char herebuf[80];
263 int debug_l;
264public:
265 void set_debug_level(int n){debug_l = n;}
266 void Debug_err(const char *fmt, ...){
267 if (debug_l >= 0) {
268 va_list ap;
269 va_start(ap, fmt);
270 vfprintf(stderr, fmt, ap);
271 va_end(ap);
272 }
273 }
274
275 void Debug_info(const char *fmt, ...){
276 if (debug_l >= 1) {
277 va_list ap;
278 va_start(ap, fmt);
279 vfprintf(stderr, fmt, ap);
280 va_end(ap);
281 }
282 }
283
284 void Debug_more(const char *fmt, ...){
285 if (debug_l >= 2) {
286 va_list ap;
287 va_start(ap, fmt);
288 vfprintf(stderr, fmt, ap);
289 va_end(ap);
290 }
291 }
292
293 const char *
294 _Here(const char *f, int n){
295 const char *p = strrchr(f, '/');
296 snprintf(herebuf, sizeof herebuf, "%s(L%d)",p?(p+1):f, n);
297 return herebuf;
298 }
299};
300
301
302#endif // __PCI_COMMON_H__
303