BasePlatformHookLib.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /** @file
  2. Platform Hook Library instances
  3. Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Uefi/UefiBaseType.h>
  8. #include <Library/PlatformHookLib.h>
  9. #include <Library/BaseLib.h>
  10. #include <Library/IoLib.h>
  11. #include <Library/PciLib.h>
  12. #include <Library/PcdLib.h>
  13. #include <SystemAgent/Include/SaAccess.h>
  14. #include <SioRegs.h>
  15. #include <Library/MmPciLib.h>
  16. #include <Library/PchCycleDecodingLib.h>
  17. #include <Register/PchRegsLpc.h>
  18. #include <PchAccess.h>
  19. #define COM1_BASE 0x3f8
  20. #define COM2_BASE 0x2f8
  21. #define SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS 0x0690
  22. #define LPC_SIO_INDEX_DEFAULT_PORT_2 0x2E
  23. #define LPC_SIO_DATA_DEFAULT_PORT_2 0x2F
  24. #define LPC_SIO_GPIO_REGISTER_ADDRESS_2 0x0A20
  25. #define LEGACY_DAUGHTER_CARD_SIO_INDEX_PORT 0x2E
  26. #define LEGACY_DAUGHTER_CARD_SIO_DATA_PORT 0x2F
  27. #define LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT 0x4E
  28. #define LEGACY_DAUGHTER_CARD_2_SIO_DATA_PORT 0x4F
  29. typedef struct {
  30. UINT8 Register;
  31. UINT8 Value;
  32. } EFI_SIO_TABLE;
  33. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioTable[] = {
  34. {0x002, 0x88}, // Power On UARTs
  35. {0x024, COM1_BASE >> 2},
  36. {0x025, COM2_BASE >> 2},
  37. {0x028, 0x043}, // IRQ of UARTs, UART2 IRQ=3,UART1 IRQ=4,
  38. {0x029, 0x080}, // SIRQ_CLKRUN_EN
  39. {0x02A, 0x000},
  40. {0x02B, 0x0DE},
  41. {0x00A, 0x040},
  42. {0x00C, 0x00E},
  43. {0x02c, 0x002},
  44. {0x030, FixedPcdGet16 (PcdSioBaseAddress) >> 4},
  45. {0x03b, SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS >> 8},
  46. {0x03c, SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS & 0xff},
  47. {0x03a, 0x00A}, // LPC Docking Enabling
  48. {0x031, 0x01f},
  49. {0x032, 0x000},
  50. {0x033, 0x004},
  51. {0x038, 0x0FB},
  52. {0x035, 0x0FE},
  53. {0x036, 0x000},
  54. {0x037, 0x0FF},
  55. {0x039, 0x000},
  56. {0x034, 0x001},
  57. {0x012, FixedPcdGet16 (PcdLpcSioConfigDefaultPort) & 0xFF}, // Relocate configuration ports base address
  58. {0x013, (FixedPcdGet16 (PcdLpcSioConfigDefaultPort) >> 8) & 0xFF} // to ensure SIO config address can be accessed in OS
  59. };
  60. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioTableSmsc1000[] = {
  61. {0x002, 0x88}, // Power On UARTs
  62. {0x007, 0x00},
  63. {0x024, COM1_BASE >> 2},
  64. {0x025, COM2_BASE >> 2},
  65. {0x028, 0x043}, // IRQ of UARTs, UART2 IRQ=3,UART1 IRQ=4,
  66. {0x029, 0x080}, // SIRQ_CLKRUN_EN
  67. {0x02A, 0x000},
  68. {0x02B, 0x0DE},
  69. {0x00A, 0x040},
  70. {0x00C, 0x00E},
  71. {0x030, FixedPcdGet16 (PcdSioBaseAddress) >> 4},
  72. {0x03b, SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS >> 8},
  73. {0x03c, SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS & 0xff},
  74. {0x03a, 0x00A}, // LPC Docking Enabling
  75. {0x031, 0x01f},
  76. {0x032, 0x000},
  77. {0x033, 0x004},
  78. {0x038, 0x0FB},
  79. {0x035, 0x0FE},
  80. {0x036, 0x000},
  81. {0x037, 0x0FE},
  82. {0x039, 0x000},
  83. {0x034, 0x001}
  84. };
  85. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioTableWpcn381u[] = {
  86. {0x29, 0x0A0}, // Enable super I/O clock and set to 48MHz
  87. {0x22, 0x003}, //
  88. {0x07, 0x003}, // Select UART0 device
  89. {0x60, (COM1_BASE >> 8)}, // Set Base Address MSB
  90. {0x61, (COM1_BASE & 0x00FF)}, // Set Base Address LSB
  91. {0x70, 0x004}, // Set to IRQ4
  92. {0x30, 0x001}, // Enable it with Activation bit
  93. {0x07, 0x002}, // Select UART1 device
  94. {0x60, (COM2_BASE >> 8)}, // Set Base Address MSB
  95. {0x61, (COM2_BASE & 0x00FF)}, // Set Base Address LSB
  96. {0x70, 0x003}, // Set to IRQ3
  97. {0x30, 0x001}, // Enable it with Activation bit
  98. {0x07, 0x007}, // Select GPIO device
  99. {0x60, (LPC_SIO_GPIO_REGISTER_ADDRESS_2 >> 8)}, // Set Base Address MSB
  100. {0x61, (LPC_SIO_GPIO_REGISTER_ADDRESS_2 & 0x00FF)}, // Set Base Address LSB
  101. {0x30, 0x001}, // Enable it with Activation bit
  102. {0x21, 0x001}, // Global Device Enable
  103. {0x26, 0x000} // Fast Enable UART 0 & 1 as their enable & activation bit
  104. };
  105. //
  106. // National PC8374L
  107. //
  108. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mDesktopSioTable[] = {
  109. {0x007, 0x03}, // Select Com1
  110. {0x061, 0xF8}, // 0x3F8
  111. {0x060, 0x03}, // 0x3F8
  112. {0x070, 0x04}, // IRQ4
  113. {0x030, 0x01} // Active
  114. };
  115. //
  116. // IT8628
  117. //
  118. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioIt8628TableSerialPort[] = {
  119. {0x023, 0x09}, // Clock Selection register
  120. {0x007, 0x01}, // Com1 Logical Device Number select
  121. {0x061, 0xF8}, // Serial Port 1 Base Address MSB Register
  122. {0x060, 0x03}, // Serial Port 1 Base Address LSB Register
  123. {0x070, 0x04}, // Serial Port 1 Interrupt Level Select
  124. {0x030, 0x01}, // Serial Port 1 Activate
  125. {0x007, 0x02}, // Com1 Logical Device Number select
  126. {0x061, 0xF8}, // Serial Port 2 Base Address MSB Register
  127. {0x060, 0x02}, // Serial Port 2 Base Address MSB Register
  128. {0x070, 0x03}, // Serial Port 2 Interrupt Level Select
  129. {0x030, 0x01} // Serial Port 2 Activate
  130. };
  131. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioIt8628TableParallelPort[] = {
  132. {0x007, 0x03}, // Parallel Port Logical Device Number select
  133. {0x030, 0x00}, // Parallel port Activate
  134. {0x061, 0x78}, // Parallel Port Base Address 1 MSB Register
  135. {0x060, 0x03}, // Parallel Port Base Address 1 LSB Register
  136. {0x063, 0x78}, // Parallel Port Base Address 2 MSB Register
  137. {0x062, 0x07}, // Parallel Port Base Address 1 LSB Register
  138. {0x0F0, 0x03} // Special Configuration register
  139. };
  140. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioTableWinbondX374[] = {
  141. {0x07, 0x03}, // Select UART0 device
  142. {0x60, (COM1_BASE >> 8)}, // Set Base Address MSB
  143. {0x61, (COM1_BASE & 0x00FF)}, // Set Base Address LSB
  144. {0x70, 0x04}, // Set to IRQ4
  145. {0x30, 0x01} // Enable it with Activation bit
  146. };
  147. GLOBAL_REMOVE_IF_UNREFERENCED EFI_SIO_TABLE mSioTablePilot3[] = {
  148. {0x07, 0x02}, // Set logical device SP Serial port Com0
  149. {0x61, 0xF8}, // Write Base Address LSB register 0x3F8
  150. {0x60, 0x03}, // Write Base Address MSB register 0x3F8
  151. {0x70, 0x04}, // Write IRQ1 value (IRQ 1) keyboard
  152. {0x30, 0x01} // Enable serial port with Activation bit
  153. };
  154. /**
  155. Detect if a National 393 SIO is docked. If yes, enable the docked SIO
  156. and its serial port, and disable the onboard serial port.
  157. @retval EFI_SUCCESS Operations performed successfully.
  158. **/
  159. STATIC
  160. VOID
  161. CheckNationalSio (
  162. VOID
  163. )
  164. {
  165. UINT8 Data8;
  166. //
  167. // Pc87393 access is through either (0x2e, 0x2f) or (0x4e, 0x4f).
  168. // We use (0x2e, 0x2f) which is determined by BADD default strapping
  169. //
  170. //
  171. // Read the Pc87393 signature
  172. //
  173. IoWrite8 (0x2e, 0x20);
  174. Data8 = IoRead8 (0x2f);
  175. if (Data8 == 0xea) {
  176. //
  177. // Signature matches - National PC87393 SIO is docked
  178. //
  179. //
  180. // Enlarge the LPC decode scope to accommodate the Docking LPC Switch
  181. // Register (SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS is allocated at
  182. // SIO_BASE_ADDRESS + 0x10)
  183. //
  184. PchLpcGenIoRangeSet ((FixedPcdGet16 (PcdSioBaseAddress) & (UINT16)~0x7F), 0x20);
  185. //
  186. // Enable port switch
  187. //
  188. IoWrite8 (SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS, 0x06);
  189. //
  190. // Turn on docking power
  191. //
  192. IoWrite8 (FixedPcdGet16 (PcdSioBaseAddress) + 0x0E, 0x8c);
  193. IoWrite8 (FixedPcdGet16 (PcdSioBaseAddress) + 0x0E, 0x9c);
  194. IoWrite8 (FixedPcdGet16 (PcdSioBaseAddress) + 0x0E, 0xBc);
  195. //
  196. // Enable port switch
  197. //
  198. IoWrite8 (SIO_DOCKING_LPC_SWITCH_REGISTER_ADDRESS, 0x7);
  199. //
  200. // GPIO setting
  201. //
  202. IoWrite8 (0x2e, 0x24);
  203. IoWrite8 (0x2f, 0x29);
  204. //
  205. // Enable chip clock
  206. //
  207. IoWrite8 (0x2e, 0x29);
  208. IoWrite8 (0x2f, 0x1e);
  209. //
  210. // Enable serial port
  211. //
  212. //
  213. // Select com1
  214. //
  215. IoWrite8 (0x2e, 0x7);
  216. IoWrite8 (0x2f, 0x3);
  217. //
  218. // Base address: 0x3f8
  219. //
  220. IoWrite8 (0x2e, 0x60);
  221. IoWrite8 (0x2f, 0x03);
  222. IoWrite8 (0x2e, 0x61);
  223. IoWrite8 (0x2f, 0xf8);
  224. //
  225. // Interrupt: 4
  226. //
  227. IoWrite8 (0x2e, 0x70);
  228. IoWrite8 (0x2f, 0x04);
  229. //
  230. // Enable bank selection
  231. //
  232. IoWrite8 (0x2e, 0xf0);
  233. IoWrite8 (0x2f, 0x82);
  234. //
  235. // Activate
  236. //
  237. IoWrite8 (0x2e, 0x30);
  238. IoWrite8 (0x2f, 0x01);
  239. //
  240. // Disable onboard serial port
  241. //
  242. IoWrite8 (FixedPcdGet16 (PcdLpcSioConfigDefaultPort), 0x55);
  243. //
  244. // Power Down UARTs
  245. //
  246. IoWrite8 (PcdGet16 (PcdLpcSioIndexPort), 0x2);
  247. IoWrite8 (PcdGet16 (PcdLpcSioDataPort), 0x00);
  248. //
  249. // Dissable COM1 decode
  250. //
  251. IoWrite8 (PcdGet16 (PcdLpcSioIndexPort), 0x24);
  252. IoWrite8 (PcdGet16 (PcdLpcSioDataPort), 0);
  253. //
  254. // Disable COM2 decode
  255. //
  256. IoWrite8 (PcdGet16 (PcdLpcSioIndexPort), 0x25);
  257. IoWrite8 (PcdGet16 (PcdLpcSioDataPort), 0);
  258. //
  259. // Disable interrupt
  260. //
  261. IoWrite8 (PcdGet16 (PcdLpcSioIndexPort), 0x28);
  262. IoWrite8 (PcdGet16 (PcdLpcSioDataPort), 0x0);
  263. IoWrite8 (FixedPcdGet16 (PcdLpcSioConfigDefaultPort), 0xAA);
  264. //
  265. // Enable floppy
  266. //
  267. //
  268. // Select floppy
  269. //
  270. IoWrite8 (0x2e, 0x7);
  271. IoWrite8 (0x2f, 0x0);
  272. //
  273. // Base address: 0x3f0
  274. //
  275. IoWrite8 (0x2e, 0x60);
  276. IoWrite8 (0x2f, 0x03);
  277. IoWrite8 (0x2e, 0x61);
  278. IoWrite8 (0x2f, 0xf0);
  279. //
  280. // Interrupt: 6
  281. //
  282. IoWrite8 (0x2e, 0x70);
  283. IoWrite8 (0x2f, 0x06);
  284. //
  285. // DMA 2
  286. //
  287. IoWrite8 (0x2e, 0x74);
  288. IoWrite8 (0x2f, 0x02);
  289. //
  290. // Activate
  291. //
  292. IoWrite8 (0x2e, 0x30);
  293. IoWrite8 (0x2f, 0x01);
  294. } else {
  295. //
  296. // No National pc87393 SIO is docked, turn off dock power and
  297. // disable port switch
  298. //
  299. // IoWrite8 (SIO_BASE_ADDRESS + 0x0E, 0xbf);
  300. // IoWrite8 (0x690, 0);
  301. //
  302. // If no National pc87393, just return
  303. //
  304. return;
  305. }
  306. }
  307. /**
  308. Check whether the IT8628 SIO present on LPC. If yes, enable its serial
  309. ports, parallel port, and port 80.
  310. @retval EFI_SUCCESS Operations performed successfully.
  311. **/
  312. STATIC
  313. VOID
  314. It8628SioSerialPortInit (
  315. VOID
  316. )
  317. {
  318. UINT8 ChipId0 = 0;
  319. UINT8 ChipId1 = 0;
  320. UINT16 LpcIoDecondeRangeSet = 0;
  321. UINT16 LpcIoDecoodeSet = 0;
  322. UINT8 Index;
  323. UINTN LpcBaseAddr;
  324. //
  325. // Enable I/O decoding for COM1 (3F8h-3FFh), COM2(2F8h-2FFh), I/O port 2Eh/2Fh.
  326. //
  327. LpcBaseAddr = MmPciBase (
  328. DEFAULT_PCI_BUS_NUMBER_PCH,
  329. PCI_DEVICE_NUMBER_PCH_LPC,
  330. PCI_FUNCTION_NUMBER_PCH_LPC
  331. );
  332. LpcIoDecondeRangeSet = (UINT16) MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOD);
  333. LpcIoDecoodeSet = (UINT16) MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOE);
  334. MmioWrite16 ((LpcBaseAddr + R_PCH_LPC_IOD), (LpcIoDecondeRangeSet | ((V_PCH_LPC_IOD_COMB_2F8 << 4) | V_PCH_LPC_IOD_COMA_3F8)));
  335. MmioWrite16 ((LpcBaseAddr + R_PCH_LPC_IOE), (LpcIoDecoodeSet | (B_PCH_LPC_IOE_SE | B_PCH_LPC_IOE_CBE | B_PCH_LPC_IOE_CAE)));
  336. //
  337. // Enter MB PnP Mode
  338. //
  339. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x87);
  340. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x01);
  341. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x55);
  342. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x55);
  343. //
  344. // Read Chip Id of SIO IT8628 (registers 0x20 and 0x21)
  345. //
  346. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x20);
  347. ChipId0 = IoRead8 (LPC_SIO_DATA_DEFAULT_PORT_2);
  348. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x21);
  349. ChipId1 = IoRead8 (LPC_SIO_DATA_DEFAULT_PORT_2);
  350. //
  351. // Enable Serial Port 1, Port 2
  352. //
  353. if ((ChipId0 == 0x86) && (ChipId1 == 0x28)) {
  354. for (Index = 0; Index < sizeof (mSioIt8628TableSerialPort) / sizeof (EFI_SIO_TABLE); Index++) {
  355. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, mSioIt8628TableSerialPort[Index].Register);
  356. IoWrite8 (LPC_SIO_DATA_DEFAULT_PORT_2, mSioIt8628TableSerialPort[Index].Value);
  357. }
  358. }
  359. //
  360. // Exit MB PnP Mode
  361. //
  362. IoWrite8 (LPC_SIO_INDEX_DEFAULT_PORT_2, 0x02);
  363. IoWrite8 (LPC_SIO_DATA_DEFAULT_PORT_2, 0x02);
  364. return;
  365. }
  366. /**
  367. Performs platform specific initialization required for the CPU to access
  368. the hardware associated with a SerialPortLib instance. This function does
  369. not initialize the serial port hardware itself. Instead, it initializes
  370. hardware devices that are required for the CPU to access the serial port
  371. hardware. This function may be called more than once.
  372. @retval RETURN_SUCCESS The platform specific initialization succeeded.
  373. @retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed.
  374. **/
  375. RETURN_STATUS
  376. EFIAPI
  377. PlatformHookSerialPortInitialize (
  378. VOID
  379. )
  380. {
  381. UINT16 ConfigPort;
  382. UINT16 IndexPort;
  383. UINT16 DataPort;
  384. UINT16 DeviceId;
  385. UINT8 Index;
  386. UINT16 AcpiBase;
  387. //
  388. // Set the ICH ACPI Base Address (Reg#40h) and ACPI Enable bit
  389. // in ACPI Controll (Reg#44h bit7) for PrePpiStall function use.
  390. //
  391. IndexPort = 0;
  392. DataPort = 0;
  393. Index = 0;
  394. AcpiBase = 0;
  395. PchAcpiBaseGet (&AcpiBase);
  396. if (AcpiBase == 0) {
  397. PchAcpiBaseSet (PcdGet16 (PcdAcpiBaseAddress));
  398. }
  399. //
  400. // Enable I/O decoding for COM1(3F8h-3FFh), COM2(2F8h-2FFh), I/O port 2Eh/2Fh, 4Eh/4Fh, 60h/64Fh and 62h/66h.
  401. //
  402. PchLpcIoDecodeRangesSet (PcdGet16 (PcdLpcIoDecodeRange));
  403. PchLpcIoEnableDecodingSet (PcdGet16 (PchLpcIoEnableDecoding));
  404. // Configure Sio IT8628
  405. It8628SioSerialPortInit ();
  406. DeviceId = MmioRead16 (MmPciBase (SA_MC_BUS, 0, 0) + R_SA_MC_DEVICE_ID);
  407. if (IS_SA_DEVICE_ID_MOBILE (DeviceId)) {
  408. //
  409. // if no EC, it is SV Bidwell Bar board
  410. //
  411. if ((IoRead8 (0x66) != 0xFF) && (IoRead8 (0x62) != 0xFF)) {
  412. //
  413. // Super I/O initialization for SMSC SI1007
  414. //
  415. ConfigPort = FixedPcdGet16 (PcdLpcSioConfigDefaultPort);
  416. DataPort = PcdGet16 (PcdLpcSioDataDefaultPort);
  417. IndexPort = PcdGet16 (PcdLpcSioIndexDefaultPort);
  418. //
  419. // 128 Byte Boundary and SIO Runtime Register Range is 0x0 to 0xF;
  420. //
  421. PchLpcGenIoRangeSet (FixedPcdGet16 (PcdSioBaseAddress) & (~0x7F), 0x10);
  422. //
  423. // Program and Enable Default Super IO Configuration Port Addresses and range
  424. //
  425. PchLpcGenIoRangeSet (FixedPcdGet16 (PcdLpcSioConfigDefaultPort) & (~0xF), 0x10);
  426. //
  427. // Enter Config Mode
  428. //
  429. IoWrite8 (ConfigPort, 0x55);
  430. //
  431. // Check for SMSC SIO1007
  432. //
  433. IoWrite8 (IndexPort, 0x0D); // SMSC SIO1007 Device ID register is 0x0D
  434. if (IoRead8 (DataPort) == 0x20) { // SMSC SIO1007 Device ID is 0x20
  435. //
  436. // Configure SIO
  437. //
  438. for (Index = 0; Index < sizeof (mSioTable) / sizeof (EFI_SIO_TABLE); Index++) {
  439. IoWrite8 (IndexPort, mSioTable[Index].Register);
  440. IoWrite8 (DataPort, mSioTable[Index].Value);
  441. }
  442. //
  443. // Exit Config Mode
  444. //
  445. IoWrite8 (FixedPcdGet16 (PcdLpcSioConfigDefaultPort), 0xAA);
  446. //
  447. // GPIO 15-17:IN 10-14:OUT Enable RS232 ref: Page42 of CRB_SCH
  448. //
  449. IoWrite8 (FixedPcdGet16 (PcdSioBaseAddress) + 0x0c, 0x1f);
  450. }
  451. //
  452. // Check if a National Pc87393 SIO is docked
  453. //
  454. CheckNationalSio ();
  455. //
  456. // Super I/O initialization for SMSC SIO1000
  457. //
  458. ConfigPort = PcdGet16 (PcdLpcSioIndexPort);
  459. IndexPort = PcdGet16 (PcdLpcSioIndexPort);
  460. DataPort = PcdGet16 (PcdLpcSioDataPort);
  461. //
  462. // Enter Config Mode
  463. //
  464. IoWrite8 (ConfigPort, 0x55);
  465. //
  466. // Check for SMSC SIO1000
  467. //
  468. if (IoRead8 (ConfigPort) != 0xFF) {
  469. //
  470. // Configure SIO
  471. //
  472. for (Index = 0; Index < sizeof (mSioTableSmsc1000) / sizeof (EFI_SIO_TABLE); Index++) {
  473. IoWrite8 (IndexPort, mSioTableSmsc1000[Index].Register);
  474. IoWrite8 (DataPort, mSioTableSmsc1000[Index].Value);
  475. }
  476. //
  477. // Exit Config Mode
  478. //
  479. IoWrite8 (FixedPcdGet16 (PcdLpcSioConfigDefaultPort), 0xAA);
  480. }
  481. //
  482. // Super I/O initialization for Winbond WPCN381U
  483. //
  484. IndexPort = LPC_SIO_INDEX_DEFAULT_PORT_2;
  485. DataPort = LPC_SIO_DATA_DEFAULT_PORT_2;
  486. //
  487. // Check for Winbond WPCN381U
  488. //
  489. IoWrite8 (IndexPort, 0x20); // Winbond WPCN381U Device ID register is 0x20
  490. if (IoRead8 (DataPort) == 0xF4) { // Winbond WPCN381U Device ID is 0xF4
  491. //
  492. // Configure SIO
  493. //
  494. for (Index = 0; Index < sizeof (mSioTableWpcn381u) / sizeof (EFI_SIO_TABLE); Index++) {
  495. IoWrite8 (IndexPort, mSioTableWpcn381u[Index].Register);
  496. IoWrite8 (DataPort, mSioTableWpcn381u[Index].Value);
  497. }
  498. }
  499. } //EC is not exist, skip mobile board detection for SV board
  500. //
  501. //add for SV Bidwell Bar board
  502. //
  503. if (IoRead8 (COM1_BASE) == 0xFF) {
  504. //
  505. // Super I/O initialization for Winbond WPCD374 (LDC2) and 8374 (LDC)
  506. // Looking for LDC2 card first
  507. //
  508. IoWrite8 (LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT, 0x55);
  509. if (IoRead8 (LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT) == 0x55) {
  510. IndexPort = LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT;
  511. DataPort = LEGACY_DAUGHTER_CARD_2_SIO_DATA_PORT;
  512. } else {
  513. IndexPort = LEGACY_DAUGHTER_CARD_SIO_INDEX_PORT;
  514. DataPort = LEGACY_DAUGHTER_CARD_SIO_DATA_PORT;
  515. }
  516. IoWrite8 (IndexPort, 0x20); // Winbond x374 Device ID register is 0x20
  517. if (IoRead8 (DataPort) == 0xF1) { // Winbond x374 Device ID is 0xF1
  518. for (Index = 0; Index < sizeof (mSioTableWinbondX374) / sizeof (EFI_SIO_TABLE); Index++) {
  519. IoWrite8 (IndexPort, mSioTableWinbondX374[Index].Register);
  520. IoWrite8 (DataPort, mSioTableWinbondX374[Index].Value);
  521. }
  522. }
  523. }// end of Bidwell Bar SIO initialization
  524. } else if (IS_SA_DEVICE_ID_DESKTOP (DeviceId) || IS_SA_DEVICE_ID_SERVER (DeviceId)) {
  525. //
  526. // If we are in debug mode, we will allow serial status codes
  527. //
  528. //
  529. // National PC8374 SIO & Winbond WPCD374 (LDC2)
  530. //
  531. IndexPort = LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT;
  532. IoWrite8 (IndexPort, 0x55);
  533. if (IoRead8 (IndexPort) == 0x55) {
  534. IndexPort = LEGACY_DAUGHTER_CARD_2_SIO_INDEX_PORT;
  535. DataPort = LEGACY_DAUGHTER_CARD_2_SIO_DATA_PORT;
  536. } else {
  537. IndexPort = LEGACY_DAUGHTER_CARD_SIO_INDEX_PORT;
  538. DataPort = LEGACY_DAUGHTER_CARD_SIO_DATA_PORT;
  539. }
  540. //
  541. // Configure SIO
  542. //
  543. IoWrite8 (IndexPort, 0x20); // Winbond x374 Device ID register is 0x20
  544. if (IoRead8 (DataPort) == 0xF1) { // Winbond x374 Device ID is 0xF1
  545. for (Index = 0; Index < sizeof (mDesktopSioTable) / sizeof (EFI_SIO_TABLE); Index++) {
  546. IoWrite8 (IndexPort, mDesktopSioTable[Index].Register);
  547. //PrePpiStall (200);
  548. IoWrite8 (DataPort, mDesktopSioTable[Index].Value);
  549. //PrePpiStall (200);
  550. }
  551. return RETURN_SUCCESS;
  552. }
  553. //
  554. // Configure Pilot3 SIO
  555. //
  556. IoWrite8 (PILOTIII_SIO_INDEX_PORT, PILOTIII_UNLOCK); //Enter config mode.
  557. IoWrite8 (PILOTIII_SIO_INDEX_PORT, PILOTIII_CHIP_ID_REG); // Pilot3 SIO Device ID register is 0x20.
  558. if (IoRead8 (PILOTIII_SIO_DATA_PORT) == PILOTIII_CHIP_ID) { // Pilot3 SIO Device ID register is 0x03.
  559. //
  560. // Configure SIO
  561. //
  562. for (Index = 0; Index < sizeof (mSioTablePilot3) / sizeof (EFI_SIO_TABLE); Index++) {
  563. IoWrite8 (PILOTIII_SIO_INDEX_PORT, mSioTablePilot3[Index].Register);
  564. IoWrite8 (PILOTIII_SIO_DATA_PORT, mSioTablePilot3[Index].Value);
  565. }
  566. }
  567. IoWrite8 (PILOTIII_SIO_INDEX_PORT , PILOTIII_LOCK); //Exit config mode.
  568. }
  569. return RETURN_SUCCESS;
  570. }