Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: pci_dev.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_DEV_NEW_H | |
24 | #define _PCI_DEV_NEW_H | |
25 | ||
26 | #include <stdio.h> | |
27 | #include <stdarg.h> | |
28 | #include "arg.h" | |
29 | #include "pci_common.h" | |
30 | #include <map> | |
31 | ||
32 | using namespace std; | |
33 | ||
34 | #define Here _Here(__FILE__, __LINE__) | |
35 | ||
36 | ||
37 | //this class encapsulates all the pci device related | |
38 | //functions. the class provides a functional level | |
39 | //model (eg simulation of optimizing pci commands is not | |
40 | //provided). | |
41 | ||
42 | //XXX Does not supports yet - | |
43 | // message signalled interrupts (msi) | |
44 | // expansion rom | |
45 | ||
46 | ||
47 | //no byte swapping is done at the device level. It is | |
48 | //assumed that the system (OS/bridge etc) will take care | |
49 | //of these issues before the data is presented to device | |
50 | ||
51 | class genericPciDev:public genericPciDevIf, pciTargetIf, pciMasterIf, pciDebug{ | |
52 | ||
53 | private: | |
54 | ||
55 | const char * busName; //name of the bus to which this device is connected | |
56 | pciBusIf *busIf; //private : no direct access to pciBus by the device specific model | |
57 | ||
58 | pciBusIf * intrptIf; | |
59 | ||
60 | int32_t device; //device number | |
61 | int32_t function; //function number | |
62 | ||
63 | public: | |
64 | pciConfSpace * confSpace; | |
65 | // functions used to map, unmap address spaces to pciBus | |
66 | bool mapBar(pci_space_t space, uint64_t base, uint64_t size){ | |
67 | assert(busIf); | |
68 | return busIf->busif_map(pciDev_getName(),space, base, size); | |
69 | } | |
70 | bool unMapBar(pci_space_t space,uint64_t base){ | |
71 | assert(busIf); | |
72 | return busIf->busif_unmap(pciDev_getName(),space, base); | |
73 | } | |
74 | ||
75 | // fakeprom devices call this function to get the | |
76 | // base address from the bus. | |
77 | uint64_t getBase(pci_space_t space, uint64_t size){ | |
78 | assert(busIf); | |
79 | return busIf->busif_get_lowest_base(space,size); | |
80 | } | |
81 | ||
82 | genericPciDev(confHeaderType htype = pciHeaderNull); | |
83 | ||
84 | // dump restore functions. the filename for dump/restore is <dir>/<filename>.pci | |
85 | bool dump(const char * dir,const char *file); | |
86 | bool restore(const char * dir, const char *file); | |
87 | // XXX only for now protected: | |
88 | public: | |
89 | ||
90 | void pciDevInfo(); | |
91 | //accessing memory from device | |
92 | //pci bus exported functions | |
93 | const char *devif_getBusName() { return busName;} | |
94 | int devif_getDevice() { return device;} | |
95 | int devif_getFunction() { return function;} | |
96 | mmi_instance_t devif_getInstance() { return pciDev_getInstance();} | |
97 | const char *devif_getName() { return pciDev_getName();} | |
98 | pciXactnStatus devif_special_cycle(uint16_t mssg, uint16_t data) { return pciTarget_special_cycle(mssg,data);} | |
99 | pciXactnStatus devif_intr_ack(uint64_t *data) { return pciTarget_intr_ack(data);} | |
100 | pciXactnStatus devif_access_w_size(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size,SAM_DeviceId * samId); | |
101 | pciXactnStatus devif_access_w_byte_enable(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable,SAM_DeviceId * samId); | |
102 | ||
103 | ||
104 | //functions to be called by specific device implementation | |
105 | //to allow parsing of busName and attach to pci bus, at right points of time. | |
106 | bool dev_parse_arg(const char *arg); /*to be called from parse_args()*/ | |
107 | bool dev_check_args(); /*to be called from check_arg()*/ | |
108 | bool dev_module_added(const char *bus_name);/*to be called from module_added()*/ | |
109 | bool dev_module_deleted(const char *target_name);/*to be called from module_deleted()*/ | |
110 | void dev_init_done(int debug_level = 0); /*to be called from init_done()*/ | |
111 | ||
112 | //fakeprom/v4 stuff. | |
113 | int dev_type; | |
114 | int slot_irl[4]; | |
115 | bool interrupt_added; | |
116 | bool int_pin_status[4]; | |
117 | ||
118 | bool isMultiFunction; //XXX to be removed when v4 dump restore is stopped being supported in v5 | |
119 | ||
120 | /* Functions that MUST be implemented by the derived class */ | |
121 | ||
122 | // to support genericPciDevIf::devif_getInstance,devif_getName | |
123 | virtual mmi_instance_t pciDev_getInstance() = 0; //return the mmi_instance | |
124 | virtual const char * pciDev_getName() = 0; //return the device instnace name | |
125 | virtual void pciDev_confAccessCb(bool_t wr, uint64_t offset, uint8_t size) = 0; | |
126 | //this function should be implemented by specific device implementation. the device | |
127 | //can perform any device specific activity related to a r/w on a particular register. | |
128 | //this is left pure virtual, so if there is no special handling then an implementation | |
129 | //must provide a function definition with empty body. | |
130 | ||
131 | ||
132 | /* functions that MAY be implemented by the derived class */ | |
133 | ||
134 | //override pci target access functions, providing a default implementation | |
135 | pciXactnStatus pciTarget_mem32access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size); | |
136 | pciXactnStatus pciTarget_mem64access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size); | |
137 | pciXactnStatus pciTarget_ioaccess(uint64_t offset, bool wr,uint64_t * buf, uint8_t size); | |
138 | pciXactnStatus pciTarget_special_cycle(uint16_t mssg, uint16_t data); | |
139 | pciXactnStatus pciTarget_intr_ack(uint64_t *data); | |
140 | ||
141 | ||
142 | // the functions a device can call as a master | |
143 | bool pciMaster_set_int(int line, bool raise); // oddball | |
144 | public: | |
145 | pciXactnStatus pciMaster_dma(bool wr, uint64_t vaddr, void *data, long count); | |
146 | protected: | |
147 | pciXactnStatus pciMaster_intr_ack_cycle(uint64_t * data); | |
148 | pciXactnStatus pciMaster_special_cycle(uint16_t mssg, uint16_t data); | |
149 | pciXactnStatus pciMaster_bus_access_w_size(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size); | |
150 | pciXactnStatus pciMaster_bus_access_w_byte_enable(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t byte_enable); | |
151 | ||
152 | ||
153 | }; | |
154 | ||
155 | ||
156 | ||
157 | class baseAddrReg:public pciConfReg{ | |
158 | /* | |
159 | Format of BAR - - - | |
160 | I/O space bit 0 - hardwired to 1 | |
161 | bit 1 - reserved, hardwired to 0 | |
162 | memory space bit 0 - hardwired to 0 | |
163 | bit [2,1] - 00 => locate anywhere in 32 bit address space | |
164 | - 01 => reserved | |
165 | - 10 => locate anywhere in 64 bit address space | |
166 | - 11 => reserved | |
167 | bit 3 - hardwired to 1 if device memory space has no side | |
168 | effects on reads and host bridge can merge writes | |
169 | into this range. (ie prefetchable) | |
170 | */ | |
171 | public: | |
172 | bool isPrefetchable; //if memory then prefetchable or not? | |
173 | uint32_t val_32To63; //upper 32 bits in case of 64 bit reg | |
174 | uint32_t mask_32To63; //mask " " " " " " etc | |
175 | uint64_t mapSize; | |
176 | bool isMapped; | |
177 | uint64_t oldVal; | |
178 | pci_space_t space; | |
179 | ||
180 | static const int IO = 0x1; //0001 | |
181 | static const int MEM32 = 0x0; //0000 | |
182 | static const int MEM64 = 0x4; //0100 | |
183 | static const int PREFETCH = 0x8; //1000 | |
184 | ||
185 | public: | |
186 | //constructor: default is mem32, non-prefetchable mapping | |
187 | baseAddrReg(const char * name, genericPciDev * d,uint64_t spaceSize,pci_space_t space , bool isPrefetchable = false); | |
188 | virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write); | |
189 | ||
190 | ||
191 | virtual void print(){ | |
192 | pciConfReg::print(); | |
193 | printf("\tSpace<%s>Size<%llx>\n",(space == PCI_MEM32 || space == PCI_MEM64)?((space == PCI_MEM32) ? "Mem32":"Mem64"):("I/O"),size); | |
194 | } | |
195 | ||
196 | void reMap(); | |
197 | ||
198 | bool map(); | |
199 | bool unmap(); | |
200 | ||
201 | }; | |
202 | ||
203 | class pciCommandReg:public pciConfReg{ | |
204 | //command register reset value is 0. Device specific model should set | |
205 | //the write mask for this register, so that the probing software can determine | |
206 | //the capabilities of the device. in general if a device does not support | |
207 | //a particular feature/operation, the corresponding mask bit should be set | |
208 | //to 0 to disable writes. | |
209 | /* | |
210 | bit # Function | |
211 | 0 Control I/O space response. Devices that do not support | |
212 | i/o access must h/w this bit to 0, ie bit 0 of write mask is 0 | |
213 | 1 Control memory space access. | |
214 | 2 Control a devices ability to act as master. Devices that do | |
215 | not generate PCI accesses must hardwire this bit to 0 | |
216 | 3 Special cycle control. | |
217 | 4 Enable bit for memory write and invalidate command. This bit | |
218 | must be hardwired to 0 if the device while acting as a master | |
219 | can not generate the command. | |
220 | 5 palette register access for VGA compatible devices | |
221 | 6 Controls devices response to parity errors | |
222 | 7 controls data/address stepping | |
223 | 8 controls SERR# driver | |
224 | 9 controls a masters ability to do fast back to back transactions | |
225 | 10-15 reserved, writes ignored, read back as 0 | |
226 | reference:pci spec rev 2.2 | |
227 | */ | |
228 | public: | |
229 | ||
230 | enum commandRegBits {IO_SPACE, MEM_SPACE, BUS_MASTER, SPECIAL_CYCLES, MWI_ENABLE, VGA_SNOOP,\ | |
231 | PARITY_RESPONSE, SERR_ENABLE, STEPPING_CTRL, FAST_B2B, NUMBITS}; | |
232 | ||
233 | pciCommandReg(const char * name, genericPciDev * d, uint16_t write_mask,uint16_t val=0):\ | |
234 | pciConfReg(name,2,val,write_mask & 0x3ff, (void *)d){ | |
235 | ||
236 | if(d == 0){ | |
237 | printf("pci command reg constructor error: must provide genericPciDev device pointer\n"); | |
238 | return; | |
239 | } | |
240 | } | |
241 | ||
242 | virtual uint8_t write(uint32_t buf, uint8_t byte_offset, uint8_t bytes_to_write); | |
243 | ||
244 | ||
245 | private: | |
246 | //try to map/unmap all the base registers if they map pci space 'spc' | |
247 | void mapSpace(pci_space_t spc); | |
248 | void unMapSpace(pci_space_t spc); | |
249 | }; | |
250 | ||
251 | class pciStatusReg:public pciConfReg{ | |
252 | //status register provides additional information about a devices | |
253 | //capabilities. This register may not be 0 at reset. A device must | |
254 | //provide the initial value of this register at reset, as well as the mask | |
255 | //describing writable bits. this register is RW1C | |
256 | //devices set the writable bits to indicate abnormal conditions during xactns. | |
257 | ||
258 | public: | |
259 | ||
260 | enum statusRegBits{ CAPABILITIES_LIST = 0x4, MHZ66 = 0x5, FAST_B2B_XACTN = 0x7, MASTER_DATA_PARITY_ERROR = 0x8,\ | |
261 | SIGNALED_TARGET_ABORT = 0xb, RECEIVED_TARGET_ABORT = 0xc, RECEIVED_MASTER_ABORT = 0xd, \ | |
262 | SIGNALED_SYSTEM_ERROR = 0xe, DETECTED_PARITY_ERROR = 0xf}; | |
263 | ||
264 | enum devselTiming { FAST = 0x0, MEDIUM = 0x1, SLOW = 0x2}; | |
265 | ||
266 | pciStatusReg(const char * name, genericPciDev * d, uint16_t init_val, uint16_t write_mask): \ | |
267 | pciConfReg(name,2,init_val, write_mask & 0xff90 ,d){ | |
268 | ||
269 | if(d == 0){ | |
270 | printf("pci status reg constructor error: must provide genericPciDev device pointer\n"); | |
271 | return; | |
272 | } | |
273 | } | |
274 | }; | |
275 | ||
276 | ||
277 | ||
278 | ||
279 | ||
280 | ||
281 | ||
282 | //COMMENTS: | |
283 | /* | |
284 | Master Abort: xactn termination by master when no targets respond. | |
285 | A master comes to know of this when DEVSEL# remains deasserted | |
286 | on clock 6. The master in this case assumes that either the | |
287 | target is incapable of responding to the command, the address was | |
288 | bad, or the target is not present and should not repeat the xactn. | |
289 | ||
290 | Target Abort: refers to an abnormal termination of a xactn that | |
291 | indicates that a target will never be able to complete the request | |
292 | or the target had a fatal error. eg unmapped csr access, misaligned | |
293 | access etc. | |
294 | ||
295 | Fast back to back xactn: refers to xactns when there are no idle | |
296 | state on the pci bus bw contiguous transactions. either the master | |
297 | or the target takes the responsibility of avoiding contention. | |
298 | If a target supports this kind xactn, then the corresponding status | |
299 | bit may be hardwired to 1. This mode is enabled by configuration s/w | |
300 | by setting the corresponding bit in command register. This bit is | |
301 | meaningful only for masters. This bit would be set in a master by s/w | |
302 | only after ensuring that all the targets are capable of these xactns. | |
303 | ||
304 | Special Cycles: this provides a simple message broadcast mechanism on | |
305 | a single pci bus segment (command does not cross bridges). No targets | |
306 | assert DEVSEL# for this command, and it terminates with a master abort | |
307 | (normal). During the address phase, the A/D lines are random. During the | |
308 | data phase AD[15::00] contain encoded message | |
309 | AD[31::16] contain message dependent options data field. | |
310 | ||
311 | ||
312 | SW requirements: | |
313 | ||
314 | 1. For non existent devices bridge must return 0xffff for reads | |
315 | of vendor id. {these accesses must be terminated with a master abort} | |
316 | 2. Conf space writes to reserved registers are no-ops ie discard the data. | |
317 | Read access to reserved or unimplemeted registers must return 0. | |
318 | 3. Device identification: The following read only registers help configuration | |
319 | s/w to determine what devices are present on system. Hence these must be | |
320 | configured for attaching drivers. | |
321 | a) vendor Id: identifies manufacturer of device. 0xffff is invalid. | |
322 | b) device id: identifies a particular device. assigned by vendor. | |
323 | ||
324 | Resource: http://pciids.sourceforge.net/pci.ids | |
325 | ||
326 | c) revision id: device specific revision id. | |
327 | d) header type: defines the layout of 2nd part of conf space. | |
328 | 00h : normal pci devices | |
329 | 01h : pci to pci bridges | |
330 | 02h : pc card standard | |
331 | e) class code: this is composed of 3 byte sized fields. | |
332 | base class code : addr 0bh broadly classifies the type of | |
333 | function the device performs. eg 02h for network controllers | |
334 | sub class code : addr 0ah identifies more specifically the | |
335 | function of the device eg 00h for ethernet controller | |
336 | programming interface : addr 09h identifies a specific register | |
337 | level programming interface( if any). | |
338 | ||
339 | Refer to Appendix D of PCI spec 2.2 for existing base and sub | |
340 | class codes. | |
341 | ||
342 | */ | |
343 | ||
344 | #endif | |
345 | ||
346 | ||
347 |