Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: schizo_module.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 | /* | |
24 | * Copyright 2004 by Sun Microsystems, Inc. | |
25 | * All rights reserved. | |
26 | * | |
27 | * W% 04/08/04 | |
28 | */ | |
29 | #ifndef _SCHIZO_MODULE_H | |
30 | #define _SCHIZO_MODULE_H | |
31 | ||
32 | #include <assert.h> | |
33 | #include <strings.h> | |
34 | #include "pci.h" | |
35 | #include "pci_dev.h" | |
36 | #include "mmi.h" | |
37 | #include "module.h" | |
38 | #include "schizo_impl.h" | |
39 | extern devRegistry * samDevs; | |
40 | ||
41 | #define MAX_SCHIZO_DEVICES 10 // 8 devices, pciA, pciB | |
42 | #define V4_MAX_SCHIZO_DEVICES 64 | |
43 | ||
44 | #define LO_U32(x) ((uint32_t)((uint32_t *)&(x))[1]) | |
45 | #define HI_U32(x) ((uint32_t)((uint32_t *)&(x))[0]) | |
46 | ||
47 | #define swap_hword(value) \ | |
48 | (((value) & 0xff) << 8 | (value) >> 8) | |
49 | ||
50 | #define swap_word(value) \ | |
51 | ((uint32_t)swap_hword((uint16_t)((value) & 0xffff)) << 16 | \ | |
52 | (uint32_t)swap_hword((uint16_t)((value) >> 16))) | |
53 | ||
54 | #define swap_lword(value) \ | |
55 | ((uint64_t)swap_word(LO_U32(value)) << 32 | \ | |
56 | (uint64_t)swap_word(HI_U32(value))) | |
57 | ||
58 | #define NUM_PAIRS 8 | |
59 | ||
60 | #define NID(X) ((X & 0x3e0) >> 5) | |
61 | typedef struct {uint64_t addr, value;} addr_val_pair; | |
62 | ||
63 | typedef enum {LEAFA, LEAFB, NLEAF} leaf_t; | |
64 | ||
65 | typedef struct pci_info { | |
66 | const char *name; | |
67 | mmi_instance_t bus; | |
68 | pciBusIf *busif; | |
69 | uint64_t base, size, mask; | |
70 | pci_space_t space; | |
71 | leaf_t leaf; | |
72 | } pci_info_t; | |
73 | ||
74 | class schizoPciDev; | |
75 | ||
76 | ||
77 | //structure to map pci devices to interrupt number. | |
78 | //each PCI device is allocated 4 interrupts, based | |
79 | //upon the slot from 0-31. The other interrupts are | |
80 | //reserved for Schizo internal interrupts, OBIO and | |
81 | //new link. | |
82 | struct pciDevIntrInfo{ | |
83 | mmi_instance_t busMod; //module pointer of bus on which device is attached | |
84 | uint8_t devNum; //sysconf device argument of device | |
85 | uint8_t devType; //type of device eg network etc | |
86 | }; | |
87 | ||
88 | ||
89 | extern "C" int schizo_access (uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf,uint8_t bytemask=PHYSIO_BYTEMASK_ALL); | |
90 | extern "C" int pci_access (uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask=PHYSIO_BYTEMASK_ALL); | |
91 | ||
92 | ||
93 | class Schizo : public Module, pciBridgeIf { | |
94 | private: | |
95 | const char *pciA, *pciB; | |
96 | pci_info_t pci_info[NLEAF][PCI_NSPACES]; | |
97 | uint64_t cpuPaddr; | |
98 | int aid; | |
99 | static const uint64_t IO_SPACE_ADDR = 0x40000000000ULL; | |
100 | static const uint64_t PCI_CONF_IO_ADDR =0x40200000000ULL; | |
101 | static const uint64_t PCI_IO_ADDR_OFFSET = 0x1000000ULL; | |
102 | static const uint64_t PCI_MEM_ADDR = 0x40400000000ULL; | |
103 | static const int NUM_ENTRIES = 16; // number of TLB/TSB entries in Schizo | |
104 | int boot_flag; | |
105 | schizo_structT* msp; | |
106 | ||
107 | bool retDevIntfA; | |
108 | schizoPciDev * pciDevA; | |
109 | schizoPciDev * pciDevB; | |
110 | pciDevIntrInfo pciIntrInfo[V4_MAX_SCHIZO_DEVICES]; | |
111 | char fkPromBus_A_Str[7]; | |
112 | char fkPromBus_B_Str[7]; | |
113 | addr_val_pair av_pairs[NUM_PAIRS]; | |
114 | ||
115 | private: | |
116 | bool dump(FILE *); | |
117 | bool restore(FILE *); | |
118 | bool restore_v4(FILE *); | |
119 | bool restore_v5(FILE *); | |
120 | void init_msp(); | |
121 | void init_mdu_regs(); | |
122 | void init_regs(); | |
123 | void init_pci(); | |
124 | void destroy_pci(); | |
125 | int rd_wr_mdu_reg(uint32_t paddr, uint64_t* buf, bool_t wr); | |
126 | Register_set regs_range(uint64_t phy_addr); | |
127 | Address_space calc_range(uint64_t *pyaddr); | |
128 | Safari_space get_range(uint64_t *pyaddr); | |
129 | int access_schizo_internals(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint32_t, uint64_t *buf,SAM_DeviceId * samId); | |
130 | int range_scsrbase(uint64_t paddr, bool_t wr, uint64_t *buf); | |
131 | int range_pci_a_csrbase(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint64_t *buf); | |
132 | int range_pci_b_csrbase(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint64_t *buf); | |
133 | int rd_wr_stc_b_diags(uint32_t paddr, uint64_t* buf, bool_t wr); | |
134 | int rd_wr_stc_a_diags(uint32_t paddr, uint64_t* buf, bool_t wr); | |
135 | ||
136 | // mmu a | |
137 | public: | |
138 | uint64_t a_iommu_va2pa(int isRead, uint64_t vaddr); | |
139 | private: | |
140 | bool_t a_flush_entry(uint32_t vaddr); | |
141 | void a_flush_entries(uint32_t context); | |
142 | bool_t a_iommu_match(Tlb_entry_t* entry, uint32_t vaddr); | |
143 | int a_get_lru_entry(); | |
144 | uint64_t a_calc_tsb_ptr( uint32_t vaddr); | |
145 | bool_t a_schizo_iommu_lookup(uint32_t vaddr); | |
146 | bool_t a_schizo_iommu_load_tte_tlb(uint32_t vaddr, uint64_t tte_entry); | |
147 | uint64_t a_translate_to_paddr(uint32_t vaddr); | |
148 | uint64_t a_vaddr2paddr(uint32_t vaddr, Tlb_entry_t* line); | |
149 | void a_update_lru_status(int num); | |
150 | int a_rd_wr_iommu_diags(uint32_t paddr, uint64_t* buf, bool_t wr); | |
151 | bool_t a_check_all_used(); | |
152 | uint64_t a_compare_entry(uint32_t vpn); | |
153 | bool_t a_any_match(Tlb_entry_t* entry, uint32_t vpn); | |
154 | ||
155 | // mmu b | |
156 | public: | |
157 | uint64_t b_iommu_va2pa(int isRead, uint64_t vaddr); | |
158 | private: | |
159 | bool_t b_flush_entry(uint32_t vaddr); | |
160 | void b_flush_entries(uint32_t context); | |
161 | bool_t b_iommu_match(Tlb_entry_t* entry, uint32_t vaddr); | |
162 | int b_get_lru_entry(); | |
163 | uint64_t b_calc_tsb_ptr( uint32_t vaddr); | |
164 | bool_t b_schizo_iommu_lookup(uint32_t vaddr); | |
165 | bool_t b_schizo_iommu_load_tte_tlb(uint32_t vaddr, uint64_t tte_entry); | |
166 | uint64_t b_translate_to_paddr(uint32_t vaddr); | |
167 | uint64_t b_vaddr2paddr(uint32_t vaddr, Tlb_entry_t* line); | |
168 | void b_update_lru_status(int num); | |
169 | int b_rd_wr_iommu_diags(uint32_t paddr, uint64_t* buf, bool_t wr); | |
170 | bool_t b_check_all_used(); | |
171 | uint64_t b_compare_entry(uint32_t vpn); | |
172 | bool_t b_any_match(Tlb_entry_t* entry, uint32_t vpn); | |
173 | ||
174 | static const uint64_t ULL(int n) { return (uint64_t)(n); }; | |
175 | static const uint64_t KB(int n) { return 1024ULL * ULL(n); }; | |
176 | static const uint64_t MB(int n) { return (1024ULL * KB(n)); }; | |
177 | static const uint64_t GB(int n) { return (1024ULL * MB(n)); }; | |
178 | static const uint64_t BIT(int n) { return 1ULL << (n); }; | |
179 | static const int LO(uint64_t n) { return (int)n; }; | |
180 | static const int HI(uint64_t n) { return (int)(n >> 32); }; | |
181 | static const int FFS(uint64_t n) { return n ? (LO(n) ? ffs(LO(n)) : (32 + ffs(HI(n)))) : 0; }; | |
182 | ||
183 | friend int schizo_access(uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf,uint8_t bytemask); | |
184 | friend int pci_access(uint32_t cpu_id, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask); | |
185 | ||
186 | int access_memory_controllers(uint32_t cpu_id, uint64_t paddr, bool_t wr, uint32_t, uint64_t *buf); | |
187 | ||
188 | void map_pci(leaf_t leaf, pci_space_t, uint64_t , uint64_t ,uint64_t); | |
189 | void unmap_pci(leaf_t leaf, pci_space_t); | |
190 | ||
191 | void send_mondo_intr(uint64_t mondo, uint32_t dev_type, uint32_t dev_id); | |
192 | int Schizo::interrupt_deassert(int indx); | |
193 | ||
194 | public: | |
195 | Schizo(const char *modname, const char *instance_name); | |
196 | ~Schizo(); | |
197 | ||
198 | public: | |
199 | int busif_add_interrupt(mmi_instance_t busMod,int device,int dev_type, int slot_irl[], bool isMulti); | |
200 | int busif_free_interrupt(mmi_instance_t busMod, int dev_number); | |
201 | int busif_interrupt_in(bool set,mmi_instance_t busMod, int device, int line, SAM_DeviceId *id); | |
202 | int busif_dma_out(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId,SAM_DeviceId *id); | |
203 | int busif_dma_in(uint64_t vaddr, void *data, long count, mmi_instance_t caller,uint16_t requesterId, SAM_DeviceId *id); | |
204 | ||
205 | // override the pciTargetIf functions. they do nothing in schizo impl. and should be never called | |
206 | ||
207 | pciXactnStatus pciTarget_mem32access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;} | |
208 | pciXactnStatus pciTarget_mem64access(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;} | |
209 | pciXactnStatus pciTarget_ioaccess(uint64_t offset, bool wr,uint64_t * buf, uint8_t size){return SIM_INTERNAL_ERROR;} | |
210 | pciXactnStatus pciTarget_special_cycle(uint16_t mssg, uint16_t data){return SIM_INTERNAL_ERROR;} | |
211 | pciXactnStatus pciTarget_intr_ack(uint64_t *data){return SIM_INTERNAL_ERROR;} | |
212 | ||
213 | // the bus number is hardwired in schizo to 0 | |
214 | int busif_get_secondary_busno(){return 0;} | |
215 | ||
216 | ||
217 | public: // Module interface | |
218 | void record_mapping(uint64_t, uint64_t); | |
219 | const char *get_help(); | |
220 | bool parse_arg(const char *); | |
221 | bool check_args(); | |
222 | void init_done(); | |
223 | void module_added(mmi_instance_t, const char*); | |
224 | void module_deleted(mmi_instance_t, const char*); | |
225 | void modinfo(); | |
226 | void *get_interface(const char*); | |
227 | ||
228 | void get_dev_props(); | |
229 | static void swapBuf(int size, uint64_t *buf); | |
230 | #ifndef V5_FAKEPROM | |
231 | int getStartInterruptIndex(mmi_instance_t busMod, int devNum); | |
232 | #endif | |
233 | ||
234 | }; | |
235 | ||
236 | ||
237 | //schizo appears as device 0 function 0 on the | |
238 | //pci buses it controls. | |
239 | ||
240 | class schizoPciDev:public genericPciDevIf{ | |
241 | ||
242 | uint8_t deviceNumber; | |
243 | uint8_t functionNumber; | |
244 | const char *busName; | |
245 | bool isBusA; | |
246 | Schizo* schizo; | |
247 | pciConfSpace * confSpace; | |
248 | ||
249 | public: | |
250 | ||
251 | ||
252 | const char *devif_getBusName(){return busName;} | |
253 | int devif_getDevice(){return deviceNumber;} | |
254 | int devif_getFunction(){return functionNumber;} | |
255 | mmi_instance_t devif_getInstance(){return schizo->getInstance();} | |
256 | const char *devif_getName(){return schizo->getName();} | |
257 | ||
258 | 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 * id){ | |
259 | if(id) *id = schizo->samId; | |
260 | return MASTER_ABORT; | |
261 | } | |
262 | ||
263 | pciXactnStatus devif_special_cycle(uint16_t mssg, uint16_t data){ | |
264 | return MASTER_ABORT; | |
265 | } | |
266 | ||
267 | pciXactnStatus devif_intr_ack(uint64_t * data){ | |
268 | return MASTER_ABORT; | |
269 | } | |
270 | ||
271 | pciXactnStatus devif_access_w_size(pci_space_t space, uint64_t paddr, uint64_t offset, bool_t wr, uint64_t* buf, uint8_t size,SAM_DeviceId * id){ | |
272 | if(id) *id = schizo->samId; | |
273 | confSpace->confAccessSize(offset,wr,buf,size); | |
274 | if(space == PCI_CFG) | |
275 | return SUCCESS; | |
276 | else | |
277 | return MASTER_ABORT; | |
278 | } | |
279 | ||
280 | schizoPciDev(Schizo * ptr,const char * bus_name, bool bus){ | |
281 | schizo = ptr; | |
282 | deviceNumber = 0; | |
283 | functionNumber = 0; | |
284 | busName = strdup(bus_name); | |
285 | isBusA = bus; | |
286 | confSpace = new pciConfSpace(pciHeaderNull); | |
287 | initPci(isBusA); | |
288 | ||
289 | }; | |
290 | private: | |
291 | void initPci(bool bus){ | |
292 | char reg_descr[100]; | |
293 | ||
294 | snprintf(reg_descr,100,"%s-%s Vendor ID", devif_getName(),busName); | |
295 | confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x108e,0x0,0x0),PCI_CONF_VENID);//0x108e, ro | |
296 | ||
297 | snprintf(reg_descr,100,"%s-%s Device ID", devif_getName(),busName); | |
298 | confSpace->addConfReg(new pciConfReg(reg_descr, 2,0x8001,0x0,0x0),PCI_CONF_DEVID); //0x8001, ro | |
299 | ||
300 | snprintf(reg_descr,100,"%s-%s command reg", devif_getName(),busName); | |
301 | confSpace->addConfReg(new pciCommandReg(reg_descr,(genericPciDev*)this,0x140,0x6),PCI_CONF_COMM);// write mask = 0x140 | |
302 | ||
303 | snprintf(reg_descr,100,"%s-%s status reg", devif_getName(),busName); | |
304 | confSpace->addConfReg(new pciStatusReg(reg_descr,(genericPciDev*)this,bus?0x280:0x2a0,0xf900),PCI_CONF_STAT);//write mask = 0xf900 | |
305 | // this reg has some rw1c bit fields. over-ride the pciStatusReg class r/w functions in case OS ever complains. | |
306 | ||
307 | snprintf(reg_descr,100,"%s-%s revision id", devif_getName(),busName); | |
308 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0,0x0),PCI_CONF_REVID);// rev id = 0x00, ro | |
309 | ||
310 | snprintf(reg_descr,100,"%s-%s prog class",devif_getName(),busName); | |
311 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_PROGCLASS);//0x00, ro | |
312 | ||
313 | snprintf(reg_descr,100,"%s-%s sub class",devif_getName(),busName); | |
314 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0x0),PCI_CONF_SUBCLASS);//0x00, ro | |
315 | ||
316 | snprintf(reg_descr,100,"%s-%s base class",devif_getName(),busName); | |
317 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x06,0x0),PCI_CONF_BASCLASS);//0x06, ro | |
318 | ||
319 | snprintf(reg_descr,100,"%s-%s latency timer",devif_getName(),busName); | |
320 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x0,0xf8),PCI_CONF_LATENCY_TIMER);//0x00, | |
321 | ||
322 | snprintf(reg_descr,100,"%s-%s Header type",devif_getName(),busName); | |
323 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0x00),PCI_CONF_HEADER); //0x00,ro | |
324 | ||
325 | snprintf(reg_descr,100,"%s-%s Bus number",devif_getName(),busName); | |
326 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),0x40); //0x00, rw | |
327 | ||
328 | snprintf(reg_descr,100,"%s-%s Subordinate bus number",devif_getName(),busName); | |
329 | confSpace->addConfReg(new pciConfReg(reg_descr,1,0x00,0xff),0x41); //0x00, rw | |
330 | } | |
331 | }; | |
332 | ||
333 | ||
334 | ||
335 | #endif /* _SCHIZO_MODULE_H */ |