PciDevice.c 14 KB

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