]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformDxe/PciDevice.c
BaseTools: Fix corner-cases of --hash feature
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformDxe / PciDevice.c
1 /** @file
2
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7
8
9 Module Name:
10
11
12 PciDevice.c
13
14 Abstract:
15
16 Platform Initialization Driver.
17
18 Revision History
19
20 --*/
21
22 #include "PlatformDxe.h"
23 #include "Library/DxeServicesTableLib.h"
24 #include "PciBus.h"
25 #include "Guid/PciLanInfo.h"
26
27 extern VOID *mPciLanInfo;
28 extern UINTN mPciLanCount;
29
30 extern EFI_HANDLE mImageHandle;
31 extern SYSTEM_CONFIGURATION mSystemConfiguration;
32
33
34 VOID *mPciRegistration;
35 #define NCR_VENDOR_ID 0x1000
36 #define ATI_VENDOR_ID 0x1002
37 #define INTEL_VENDOR_ID 0x8086
38 #define ATI_RV423_ID 0x5548
39 #define ATI_RV423_ID2 0x5d57
40 #define ATI_RV380_ID 0x3e50
41 #define ATI_RV370_ID 0x5b60
42 #define SI_VENDOR_ID 0x1095
43 #define SI_SISATA_ID 0x3114
44 #define SI_SIRAID_PCIUNL 0x40
45 #define INTEL_82573E_IDER 0x108D
46
47 typedef struct {
48 UINT8 ClassCode;
49 UINT8 SubClassCode;
50 UINT16 VendorId;
51 UINT16 DeviceId;
52 } BAD_DEVICE_TABLE;
53
54 BAD_DEVICE_TABLE BadDeviceTable[] = {
55 {(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_SCSI,(UINT16)NCR_VENDOR_ID, (UINT16)0xffff}, // Any NCR cards
56 {(UINT8)PCI_CLASS_MASS_STORAGE,(UINT8)PCI_CLASS_MASS_STORAGE_IDE,(UINT16)INTEL_VENDOR_ID, (UINT16)INTEL_82573E_IDER}, // Intel i82573E Tekoa GBit Lan IDE-R
57 {(UINT8)0xff,(UINT8)0xff,(UINT16)0xffff,(UINT16)0xffff}
58 };
59
60 EFI_STATUS
61 PciBusDriverHook (
62 )
63 {
64 EFI_STATUS Status;
65 EFI_EVENT FilterEvent;
66
67 //
68 // Register for callback to PCI I/O protocol
69 //
70 Status = gBS->CreateEvent (
71 EVT_NOTIFY_SIGNAL,
72 TPL_CALLBACK,
73 PciBusEvent,
74 NULL,
75 &FilterEvent
76 );
77 ASSERT_EFI_ERROR(Status);
78
79 //
80 // Register for protocol notifications on this event
81 //
82 Status = gBS->RegisterProtocolNotify (
83 &gEfiPciIoProtocolGuid,
84 FilterEvent,
85 &mPciRegistration
86 );
87 ASSERT_EFI_ERROR (Status);
88
89 return EFI_SUCCESS;
90 }
91
92 VOID
93 InitBadBars(
94 IN EFI_PCI_IO_PROTOCOL *PciIo,
95 IN UINT16 VendorId,
96 IN UINT16 DeviceId
97 )
98 {
99
100 UINT64 BaseAddress = 0;
101 UINT64 TempBaseAddress = 0;
102 UINT8 RevId = 0;
103 UINT32 Bar;
104 UINT64 IoSize;
105 UINT64 MemSize;
106 UINTN MemSizeBits;
107
108 switch ( VendorId) {
109 case ATI_VENDOR_ID:
110 //
111 // ATI fix-ups. At this time all ATI cards in BadDeviceTable
112 // have same problem in that OPROM BAR needs to be increased.
113 //
114 Bar = 0x30 ;
115 //
116 // Get original BAR address
117 //
118 PciIo->Pci.Read (
119 PciIo,
120 EfiPciIoWidthUint32,
121 Bar,
122 1,
123 (VOID *) &BaseAddress
124 );
125 //
126 // Find BAR size
127 //
128 TempBaseAddress = 0xffffffff;
129 PciIo->Pci.Write (
130 PciIo,
131 EfiPciIoWidthUint32,
132 Bar,
133 1,
134 (VOID *) &TempBaseAddress
135 );
136 PciIo->Pci.Read (
137 PciIo,
138 EfiPciIoWidthUint32,
139 Bar,
140 1,
141 (VOID *) &TempBaseAddress
142 );
143 TempBaseAddress &= 0xfffffffe;
144 MemSize = 1;
145 while ((TempBaseAddress & 0x01) == 0) {
146 TempBaseAddress = TempBaseAddress >> 1;
147 MemSize = MemSize << 1;
148 }
149
150 //
151 // Free up allocated memory memory and re-allocate with increased size.
152 //
153 gDS->FreeMemorySpace (
154 BaseAddress,
155 MemSize
156 );
157 //
158 // Force new alignment
159 //
160 MemSize = 0x8000000;
161 MemSizeBits = 28;
162
163 gDS->AllocateMemorySpace (
164 EfiGcdAllocateAnySearchBottomUp,
165 EfiGcdMemoryTypeMemoryMappedIo,
166 MemSizeBits, // Alignment
167 MemSize,
168 &BaseAddress,
169 mImageHandle,
170 NULL
171 );
172 PciIo->Pci.Write (
173 PciIo,
174 EfiPciIoWidthUint32,
175 Bar,
176 1,
177 (VOID *) &BaseAddress
178 );
179
180 break;
181 case NCR_VENDOR_ID:
182 #define MIN_NCR_IO_SIZE 0x800
183 #define NCR_GRAN 11 // 2**11 = 0x800
184 //
185 // NCR SCSI cards like 8250S lie about IO needed. Assign as least 0x80.
186 //
187 for (Bar = 0x10; Bar < 0x28; Bar+= 4) {
188
189 PciIo->Pci.Read (
190 PciIo,
191 EfiPciIoWidthUint32,
192 Bar,
193 1,
194 (VOID *) &BaseAddress
195 );
196 if (BaseAddress && 0x01) {
197 TempBaseAddress = 0xffffffff;
198 PciIo->Pci.Write (
199 PciIo,
200 EfiPciIoWidthUint32,
201 Bar,
202 1,
203 (VOID *) &TempBaseAddress
204 );
205 TempBaseAddress &= 0xfffffffc;
206 IoSize = 1;
207 while ((TempBaseAddress & 0x01) == 0) {
208 TempBaseAddress = TempBaseAddress >> 1;
209 IoSize = IoSize << 1;
210 }
211 if (IoSize < MIN_NCR_IO_SIZE) {
212 gDS->FreeIoSpace (
213 BaseAddress,
214 IoSize
215 );
216
217 gDS->AllocateIoSpace (
218 EfiGcdAllocateAnySearchTopDown,
219 EfiGcdIoTypeIo,
220 NCR_GRAN, // Alignment
221 MIN_NCR_IO_SIZE,
222 &BaseAddress,
223 mImageHandle,
224 NULL
225 );
226 TempBaseAddress = BaseAddress + 1;
227 PciIo->Pci.Write (
228 PciIo,
229 EfiPciIoWidthUint32,
230 Bar,
231 1,
232 (VOID *) &TempBaseAddress
233 );
234 }
235 }
236 }
237
238 break;
239
240 case INTEL_VENDOR_ID:
241 if (DeviceId == INTEL_82573E_IDER) {
242 //
243 // Tekoa i82573E IDE-R fix-ups. At this time A2 step and earlier parts do not
244 // support any BARs except BAR0. Other BARS will actualy map to BAR0 so disable
245 // them all for Control Blocks and Bus mastering ops as well as Secondary IDE
246 // Controller.
247 // All Tekoa A2 or earlier step chips for now.
248 //
249 PciIo->Pci.Read (
250 PciIo,
251 EfiPciIoWidthUint8,
252 PCI_REVISION_ID_OFFSET,
253 1,
254 &RevId
255 );
256 if (RevId <= 0x02) {
257 for (Bar = 0x14; Bar < 0x24; Bar+= 4) {
258 //
259 // Maybe want to clean this up a bit later but for now just clear out the secondary
260 // Bars don't worry aboyut freeing up thge allocs.
261 //
262 TempBaseAddress = 0x0;
263 PciIo->Pci.Write (
264 PciIo,
265 EfiPciIoWidthUint32,
266 Bar,
267 1,
268 (VOID *) &TempBaseAddress
269 );
270 } // end for
271 }
272 else
273 {
274 //
275 //Tekoa A3 or above:
276 //Clear bus master base address (PCI register 0x20)
277 //since Tekoa does not fully support IDE Bus Mastering
278 //
279 TempBaseAddress = 0x0;
280 PciIo->Pci.Write (
281 PciIo,
282 EfiPciIoWidthUint32,
283 0x20,
284 1,
285 (VOID *) &TempBaseAddress
286 );
287 }
288 }
289 break;
290
291 default:
292 break;
293 }
294 return;
295 }
296
297 VOID
298 ProgramPciLatency(
299 IN EFI_PCI_IO_PROTOCOL *PciIo
300 )
301 {
302 //
303 // Program Master Latency Timer
304 //
305 if (mSystemConfiguration.PciLatency != 0) {
306 PciIo->Pci.Write (
307 PciIo,
308 EfiPciIoWidthUint8,
309 PCI_LATENCY_TIMER_OFFSET,
310 1,
311 &mSystemConfiguration.PciLatency
312 );
313 }
314 return;
315 }
316
317 /**
318 During S5 shutdown, we need to program PME in all LAN devices.
319 Here we identify LAN devices and save their bus/dev/func.
320
321 **/
322 VOID
323 SavePciLanAddress(
324 IN EFI_PCI_IO_PROTOCOL *PciIo
325 )
326 {
327 EFI_STATUS Status;
328 UINTN PciSegment,
329 PciBus,
330 PciDevice,
331 PciFunction;
332 VOID *NewBuffer;
333 PCI_LAN_INFO *x;
334
335 Status = PciIo->GetLocation (
336 PciIo,
337 &PciSegment,
338 &PciBus,
339 &PciDevice,
340 &PciFunction
341 );
342 if (EFI_ERROR (Status)) {
343 return;
344 }
345
346 mPciLanCount ++;
347 Status = gBS->AllocatePool (
348 EfiBootServicesData,
349 mPciLanCount * sizeof(PCI_LAN_INFO),
350 &NewBuffer
351 );
352 if (EFI_ERROR (Status)) {
353 return;
354 }
355
356 if (mPciLanCount > 1) {
357 //
358 // copy old data into new, larger buffer
359 //
360 gBS->CopyMem (
361 NewBuffer,
362 mPciLanInfo,
363 (mPciLanCount - 1) * sizeof(PCI_LAN_INFO)
364 );
365
366 //
367 // free the old memory buffer
368 //
369 gBS->FreePool (mPciLanInfo);
370
371 }
372
373 //
374 // init the new entry
375 //
376 x = (PCI_LAN_INFO *)NewBuffer + (mPciLanCount - 1);
377 x->PciBus = (UINT8)PciBus;
378 x->PciDevice = (UINT8)PciDevice;
379 x->PciFunction = (UINT8)PciFunction;
380
381 mPciLanInfo = NewBuffer;
382
383 return;
384 }
385
386 /**
387 @param Event the event that is signaled.
388 @param Context not used here.
389
390
391 **/
392 VOID
393 EFIAPI
394 PciBusEvent (
395 IN EFI_EVENT Event,
396 IN VOID* Context
397 )
398 {
399
400 EFI_STATUS Status;
401 UINTN BufferSize;
402 EFI_HANDLE Handle;
403 EFI_PCI_IO_PROTOCOL *PciIo;
404 PCI_IO_DEVICE *PciIoDevice;
405 UINT64 Supports;
406 UINTN Index;
407 UINT8 mCacheLineSize = 0x10;
408
409 while (TRUE) {
410 BufferSize = sizeof (EFI_HANDLE);
411 Status = gBS->LocateHandle (
412 ByRegisterNotify,
413 NULL,
414 mPciRegistration,
415 &BufferSize,
416 &Handle
417 );
418 if (EFI_ERROR (Status)) {
419 //
420 // If no more notification events exist
421 //
422 return;
423 }
424
425 Status = gBS->HandleProtocol (
426 Handle,
427 &gEfiPciIoProtocolGuid,
428 (void **)&PciIo
429 );
430
431 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
432
433 //
434 // Enable I/O for bridge so port 0x80 codes will come out
435 //
436 if (PciIoDevice->Pci.Hdr.VendorId == V_PCH_INTEL_VENDOR_ID)
437 {
438 Status = PciIo->Attributes(
439 PciIo,
440 EfiPciIoAttributeOperationSupported,
441 0,
442 &Supports
443 );
444 Supports &= EFI_PCI_DEVICE_ENABLE;
445 Status = PciIo->Attributes (
446 PciIo,
447 EfiPciIoAttributeOperationEnable,
448 Supports,
449 NULL
450 );
451 break;
452 }
453
454 //
455 // Program PCI Latency Timer
456 //
457 ProgramPciLatency(PciIo);
458
459 //
460 // Program Cache Line Size to 64 bytes (0x10 DWORDs)
461 //
462 Status = PciIo->Pci.Write (
463 PciIo,
464 EfiPciIoWidthUint8,
465 PCI_CACHELINE_SIZE_OFFSET,
466 1,
467 &mCacheLineSize
468 );
469
470 //
471 // If PCI LAN device, save bus/dev/func info
472 // so we can program PME during S5 shutdown
473 //
474 if (PciIoDevice->Pci.Hdr.ClassCode[2] == PCI_CLASS_NETWORK) {
475 SavePciLanAddress(PciIo);
476 break;
477 }
478
479 //
480 // Workaround for cards with bad BARs
481 //
482 Index = 0;
483 while (BadDeviceTable[Index].ClassCode != 0xff) {
484 if (BadDeviceTable[Index].DeviceId == 0xffff) {
485 if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) &&
486 (PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) &&
487 (PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId)) {
488 InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId);
489 }
490 } else {
491 if ((PciIoDevice->Pci.Hdr.ClassCode[2] == BadDeviceTable[Index].ClassCode) &&
492 (PciIoDevice->Pci.Hdr.ClassCode[1] == BadDeviceTable[Index].SubClassCode) &&
493 (PciIoDevice->Pci.Hdr.VendorId == BadDeviceTable[Index].VendorId) &&
494 (PciIoDevice->Pci.Hdr.DeviceId == BadDeviceTable[Index].DeviceId)) {
495
496 InitBadBars(PciIo,BadDeviceTable[Index].VendorId,BadDeviceTable[Index].DeviceId);
497 }
498 }
499 ++Index;
500 }
501 break;
502 }
503
504 return;
505 }
506