LsiScsi.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  1. /** @file
  2. This driver produces Extended SCSI Pass Thru Protocol instances for
  3. LSI 53C895A SCSI devices.
  4. Copyright (C) 2020, SUSE LLC.
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <IndustryStandard/LsiScsi.h>
  8. #include <IndustryStandard/Pci.h>
  9. #include <Library/BaseLib.h>
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/DebugLib.h>
  12. #include <Library/MemoryAllocationLib.h>
  13. #include <Library/PcdLib.h>
  14. #include <Library/UefiBootServicesTableLib.h>
  15. #include <Library/UefiLib.h>
  16. #include <Protocol/PciIo.h>
  17. #include <Protocol/PciRootBridgeIo.h>
  18. #include <Protocol/ScsiPassThruExt.h>
  19. #include <Uefi/UefiSpec.h>
  20. #include "LsiScsi.h"
  21. STATIC
  22. EFI_STATUS
  23. Out8 (
  24. IN LSI_SCSI_DEV *Dev,
  25. IN UINT32 Addr,
  26. IN UINT8 Data
  27. )
  28. {
  29. return Dev->PciIo->Io.Write (
  30. Dev->PciIo,
  31. EfiPciIoWidthUint8,
  32. PCI_BAR_IDX0,
  33. Addr,
  34. 1,
  35. &Data
  36. );
  37. }
  38. STATIC
  39. EFI_STATUS
  40. Out32 (
  41. IN LSI_SCSI_DEV *Dev,
  42. IN UINT32 Addr,
  43. IN UINT32 Data
  44. )
  45. {
  46. return Dev->PciIo->Io.Write (
  47. Dev->PciIo,
  48. EfiPciIoWidthUint32,
  49. PCI_BAR_IDX0,
  50. Addr,
  51. 1,
  52. &Data
  53. );
  54. }
  55. STATIC
  56. EFI_STATUS
  57. In8 (
  58. IN LSI_SCSI_DEV *Dev,
  59. IN UINT32 Addr,
  60. OUT UINT8 *Data
  61. )
  62. {
  63. return Dev->PciIo->Io.Read (
  64. Dev->PciIo,
  65. EfiPciIoWidthUint8,
  66. PCI_BAR_IDX0,
  67. Addr,
  68. 1,
  69. Data
  70. );
  71. }
  72. STATIC
  73. EFI_STATUS
  74. In32 (
  75. IN LSI_SCSI_DEV *Dev,
  76. IN UINT32 Addr,
  77. OUT UINT32 *Data
  78. )
  79. {
  80. return Dev->PciIo->Io.Read (
  81. Dev->PciIo,
  82. EfiPciIoWidthUint32,
  83. PCI_BAR_IDX0,
  84. Addr,
  85. 1,
  86. Data
  87. );
  88. }
  89. STATIC
  90. EFI_STATUS
  91. LsiScsiReset (
  92. IN LSI_SCSI_DEV *Dev
  93. )
  94. {
  95. return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
  96. }
  97. STATIC
  98. EFI_STATUS
  99. ReportHostAdapterOverrunError (
  100. OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
  101. )
  102. {
  103. Packet->SenseDataLength = 0;
  104. Packet->HostAdapterStatus =
  105. EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
  106. Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
  107. return EFI_BAD_BUFFER_SIZE;
  108. }
  109. /**
  110. Check the request packet from the Extended SCSI Pass Thru Protocol. The
  111. request packet is modified, to be forwarded outwards by LsiScsiPassThru(),
  112. if invalid or unsupported parameters are detected.
  113. @param[in] Dev The LSI 53C895A SCSI device the packet targets.
  114. @param[in] Target The SCSI target controlled by the LSI 53C895A SCSI
  115. device.
  116. @param[in] Lun The Logical Unit Number under the SCSI target.
  117. @param[in out] Packet The Extended SCSI Pass Thru Protocol packet.
  118. @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid.
  119. @return Otherwise, invalid or unsupported parameters were
  120. detected. Status codes are meant for direct forwarding
  121. by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
  122. implementation.
  123. **/
  124. STATIC
  125. EFI_STATUS
  126. LsiScsiCheckRequest (
  127. IN LSI_SCSI_DEV *Dev,
  128. IN UINT8 Target,
  129. IN UINT64 Lun,
  130. IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
  131. )
  132. {
  133. if ((Target > Dev->MaxTarget) || (Lun > Dev->MaxLun) ||
  134. (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
  135. //
  136. // Trying to receive, but destination pointer is NULL, or contradicting
  137. // transfer direction
  138. //
  139. ((Packet->InTransferLength > 0) &&
  140. ((Packet->InDataBuffer == NULL) ||
  141. (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)
  142. )
  143. ) ||
  144. //
  145. // Trying to send, but source pointer is NULL, or contradicting transfer
  146. // direction
  147. //
  148. ((Packet->OutTransferLength > 0) &&
  149. ((Packet->OutDataBuffer == NULL) ||
  150. (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)
  151. )
  152. )
  153. )
  154. {
  155. return EFI_INVALID_PARAMETER;
  156. }
  157. if ((Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
  158. ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0)) ||
  159. (Packet->CdbLength > sizeof Dev->Dma->Cdb))
  160. {
  161. return EFI_UNSUPPORTED;
  162. }
  163. if (Packet->InTransferLength > sizeof Dev->Dma->Data) {
  164. Packet->InTransferLength = sizeof Dev->Dma->Data;
  165. return ReportHostAdapterOverrunError (Packet);
  166. }
  167. if (Packet->OutTransferLength > sizeof Dev->Dma->Data) {
  168. Packet->OutTransferLength = sizeof Dev->Dma->Data;
  169. return ReportHostAdapterOverrunError (Packet);
  170. }
  171. return EFI_SUCCESS;
  172. }
  173. /**
  174. Interpret the request packet from the Extended SCSI Pass Thru Protocol and
  175. compose the script to submit the command and data to the controller.
  176. @param[in] Dev The LSI 53C895A SCSI device the packet targets.
  177. @param[in] Target The SCSI target controlled by the LSI 53C895A SCSI
  178. device.
  179. @param[in] Lun The Logical Unit Number under the SCSI target.
  180. @param[in out] Packet The Extended SCSI Pass Thru Protocol packet.
  181. @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid.
  182. @return Otherwise, invalid or unsupported parameters were
  183. detected. Status codes are meant for direct forwarding
  184. by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
  185. implementation.
  186. **/
  187. STATIC
  188. EFI_STATUS
  189. LsiScsiProcessRequest (
  190. IN LSI_SCSI_DEV *Dev,
  191. IN UINT8 Target,
  192. IN UINT64 Lun,
  193. IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
  194. )
  195. {
  196. EFI_STATUS Status;
  197. UINT32 *Script;
  198. UINT8 *Cdb;
  199. UINT8 *MsgOut;
  200. UINT8 *MsgIn;
  201. UINT8 *ScsiStatus;
  202. UINT8 *Data;
  203. UINT8 DStat;
  204. UINT8 SIst0;
  205. UINT8 SIst1;
  206. UINT32 Csbc;
  207. UINT32 CsbcBase;
  208. UINT32 Transferred;
  209. Script = Dev->Dma->Script;
  210. Cdb = Dev->Dma->Cdb;
  211. Data = Dev->Dma->Data;
  212. MsgIn = Dev->Dma->MsgIn;
  213. MsgOut = &Dev->Dma->MsgOut;
  214. ScsiStatus = &Dev->Dma->Status;
  215. *ScsiStatus = 0xFF;
  216. DStat = 0;
  217. SIst0 = 0;
  218. SIst1 = 0;
  219. SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
  220. CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
  221. //
  222. // Fetch the first Cumulative SCSI Byte Count (CSBC).
  223. //
  224. // CSBC is a cumulative counter of the actual number of bytes that have been
  225. // transferred across the SCSI bus during data phases, i.e. it will not
  226. // count bytes sent in command, status, message in and out phases.
  227. //
  228. Status = In32 (Dev, LSI_REG_CSBC, &CsbcBase);
  229. if (EFI_ERROR (Status)) {
  230. goto Error;
  231. }
  232. //
  233. // Clean up the DMA buffer for the script.
  234. //
  235. SetMem (Script, sizeof Dev->Dma->Script, 0x00);
  236. //
  237. // Compose the script to transfer data between the host and the device.
  238. //
  239. // References:
  240. // * LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
  241. // - Chapter 5 SCSI SCRIPT Instruction Set
  242. // * SEABIOS lsi-scsi driver
  243. //
  244. // All instructions used here consist of 2 32bit words. The first word
  245. // contains the command to execute. The second word is loaded into the
  246. // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
  247. // for data transmission or the address/offset for the jump command.
  248. // Some commands, such as the selection of the target, don't need to
  249. // transfer data through DMA or jump to another instruction, then DSPS
  250. // has to be zero.
  251. //
  252. // There are 3 major parts in this script. The first part (1~3) contains
  253. // the instructions to select target and LUN and send the SCSI command
  254. // from the request packet. The second part (4~7) is to handle the
  255. // potential disconnection and prepare for the data transmission. The
  256. // instructions in the third part (8~10) transmit the given data and
  257. // collect the result. Instruction 11 raises the interrupt and marks the
  258. // end of the script.
  259. //
  260. //
  261. // 1. Select target.
  262. //
  263. *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
  264. *Script++ = 0x00000000;
  265. //
  266. // 2. Select LUN.
  267. //
  268. *MsgOut = 0x80 | (UINT8)Lun; // 0x80: Identify bit
  269. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT |
  270. (UINT32)sizeof Dev->Dma->MsgOut;
  271. *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgOut);
  272. //
  273. // 3. Send the SCSI Command.
  274. //
  275. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD |
  276. (UINT32)sizeof Dev->Dma->Cdb;
  277. *Script++ = LSI_SCSI_DMA_ADDR (Dev, Cdb);
  278. //
  279. // 4. Check whether the current SCSI phase is "Message In" or not
  280. // and jump to 7 if it is.
  281. // Note: LSI_INS_TC_RA stands for "Relative Address Mode", so the
  282. // offset 0x18 in the second word means jumping forward
  283. // 3 (0x18/8) instructions.
  284. //
  285. *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP |
  286. LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA |
  287. LSI_INS_TC_CP;
  288. *Script++ = 0x00000018;
  289. //
  290. // 5. Read "Message" from the initiator to trigger reselect.
  291. //
  292. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
  293. (UINT32)sizeof Dev->Dma->MsgIn;
  294. *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
  295. //
  296. // 6. Wait reselect.
  297. //
  298. *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
  299. *Script++ = 0x00000000;
  300. //
  301. // 7. Read "Message" from the initiator again
  302. //
  303. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
  304. (UINT32)sizeof Dev->Dma->MsgIn;
  305. *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
  306. //
  307. // 8. Set the DMA command for the read/write operations.
  308. // Note: Some requests, e.g. "TEST UNIT READY", do not come with
  309. // allocated InDataBuffer or OutDataBuffer. We skip the DMA
  310. // data command for those requests or this script would fail
  311. // with LSI_SIST0_SGE due to the zero data length.
  312. //
  313. // LsiScsiCheckRequest() prevents both integer overflows in the command
  314. // opcodes, and buffer overflows.
  315. //
  316. if (Packet->InTransferLength > 0) {
  317. ASSERT (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ);
  318. ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
  319. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
  320. Packet->InTransferLength;
  321. *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
  322. } else if (Packet->OutTransferLength > 0) {
  323. ASSERT (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE);
  324. ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
  325. CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
  326. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
  327. Packet->OutTransferLength;
  328. *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
  329. }
  330. //
  331. // 9. Get the SCSI status.
  332. //
  333. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT |
  334. (UINT32)sizeof Dev->Dma->Status;
  335. *Script++ = LSI_SCSI_DMA_ADDR (Dev, Status);
  336. //
  337. // 10. Get the SCSI message.
  338. //
  339. *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
  340. (UINT32)sizeof Dev->Dma->MsgIn;
  341. *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
  342. //
  343. // 11. Raise the interrupt to end the script.
  344. //
  345. *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT |
  346. LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
  347. *Script++ = 0x00000000;
  348. //
  349. // Make sure the size of the script doesn't exceed the buffer.
  350. //
  351. ASSERT (Script <= Dev->Dma->Script + ARRAY_SIZE (Dev->Dma->Script));
  352. //
  353. // The controller starts to execute the script once the DMA Script
  354. // Pointer (DSP) register is set.
  355. //
  356. Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR (Dev, Script));
  357. if (EFI_ERROR (Status)) {
  358. goto Error;
  359. }
  360. //
  361. // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
  362. // bit sets.
  363. //
  364. for ( ; ;) {
  365. Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
  366. if (EFI_ERROR (Status)) {
  367. goto Error;
  368. }
  369. Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
  370. if (EFI_ERROR (Status)) {
  371. goto Error;
  372. }
  373. Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
  374. if (EFI_ERROR (Status)) {
  375. goto Error;
  376. }
  377. if ((SIst0 != 0) || (SIst1 != 0)) {
  378. goto Error;
  379. }
  380. //
  381. // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
  382. //
  383. if (DStat & LSI_DSTAT_SIR) {
  384. break;
  385. }
  386. gBS->Stall (Dev->StallPerPollUsec);
  387. }
  388. //
  389. // Check if everything is good.
  390. // SCSI Message Code 0x00: COMMAND COMPLETE
  391. // SCSI Status Code 0x00: Good
  392. //
  393. if ((MsgIn[0] != 0) || (*ScsiStatus != 0)) {
  394. goto Error;
  395. }
  396. //
  397. // Fetch CSBC again to calculate the transferred bytes and update
  398. // InTransferLength/OutTransferLength.
  399. //
  400. // Note: The number of transferred bytes is bounded by
  401. // "sizeof Dev->Dma->Data", so it's safe to subtract CsbcBase
  402. // from Csbc. If the CSBC register wraps around, the correct
  403. // difference is ensured by the standard C modular arithmetic.
  404. //
  405. Status = In32 (Dev, LSI_REG_CSBC, &Csbc);
  406. if (EFI_ERROR (Status)) {
  407. goto Error;
  408. }
  409. Transferred = Csbc - CsbcBase;
  410. if (Packet->InTransferLength > 0) {
  411. if (Transferred <= Packet->InTransferLength) {
  412. Packet->InTransferLength = Transferred;
  413. } else {
  414. goto Error;
  415. }
  416. } else if (Packet->OutTransferLength > 0) {
  417. if (Transferred <= Packet->OutTransferLength) {
  418. Packet->OutTransferLength = Transferred;
  419. } else {
  420. goto Error;
  421. }
  422. }
  423. //
  424. // Copy Data to InDataBuffer if necessary.
  425. //
  426. if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
  427. CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
  428. }
  429. //
  430. // Always set SenseDataLength to 0.
  431. // The instructions of LSI53C895A don't reply sense data. Instead, it
  432. // relies on the SCSI command, "REQUEST SENSE", to get sense data. We set
  433. // SenseDataLength to 0 to notify ScsiDiskDxe that there is no sense data
  434. // written even if this request is processed successfully, so that It will
  435. // issue "REQUEST SENSE" later to retrieve sense data.
  436. //
  437. Packet->SenseDataLength = 0;
  438. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
  439. Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
  440. return EFI_SUCCESS;
  441. Error:
  442. DEBUG ((
  443. DEBUG_VERBOSE,
  444. "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
  445. __FUNCTION__,
  446. DStat,
  447. SIst0,
  448. SIst1
  449. ));
  450. //
  451. // Update the request packet to reflect the status.
  452. //
  453. if (*ScsiStatus != 0xFF) {
  454. Packet->TargetStatus = *ScsiStatus;
  455. } else {
  456. Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
  457. }
  458. if (SIst0 & LSI_SIST0_PAR) {
  459. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR;
  460. } else if (SIst0 & LSI_SIST0_RST) {
  461. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;
  462. } else if (SIst0 & LSI_SIST0_UDC) {
  463. //
  464. // The target device is disconnected unexpectedly. According to UEFI spec,
  465. // this is TIMEOUT_COMMAND.
  466. //
  467. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
  468. } else if (SIst0 & LSI_SIST0_SGE) {
  469. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
  470. } else if (SIst1 & LSI_SIST1_HTH) {
  471. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT;
  472. } else if (SIst1 & LSI_SIST1_GEN) {
  473. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT;
  474. } else if (SIst1 & LSI_SIST1_STO) {
  475. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
  476. } else {
  477. Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
  478. }
  479. //
  480. // SenseData may be used to inspect the error. Since we don't set sense data,
  481. // SenseDataLength has to be 0.
  482. //
  483. Packet->SenseDataLength = 0;
  484. return EFI_DEVICE_ERROR;
  485. }
  486. //
  487. // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
  488. // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
  489. // sections
  490. // - 14.1 SCSI Driver Model Overview,
  491. // - 14.7 Extended SCSI Pass Thru Protocol.
  492. //
  493. EFI_STATUS
  494. EFIAPI
  495. LsiScsiPassThru (
  496. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  497. IN UINT8 *Target,
  498. IN UINT64 Lun,
  499. IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
  500. IN EFI_EVENT Event OPTIONAL
  501. )
  502. {
  503. EFI_STATUS Status;
  504. LSI_SCSI_DEV *Dev;
  505. Dev = LSI_SCSI_FROM_PASS_THRU (This);
  506. Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
  507. if (EFI_ERROR (Status)) {
  508. return Status;
  509. }
  510. return LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
  511. }
  512. EFI_STATUS
  513. EFIAPI
  514. LsiScsiGetNextTargetLun (
  515. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  516. IN OUT UINT8 **TargetPointer,
  517. IN OUT UINT64 *Lun
  518. )
  519. {
  520. LSI_SCSI_DEV *Dev;
  521. UINTN Idx;
  522. UINT8 *Target;
  523. UINT16 LastTarget;
  524. //
  525. // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
  526. //
  527. Target = *TargetPointer;
  528. //
  529. // Search for first non-0xFF byte. If not found, return first target & LUN.
  530. //
  531. for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {
  532. }
  533. if (Idx == TARGET_MAX_BYTES) {
  534. SetMem (Target, TARGET_MAX_BYTES, 0x00);
  535. *Lun = 0;
  536. return EFI_SUCCESS;
  537. }
  538. CopyMem (&LastTarget, Target, sizeof LastTarget);
  539. //
  540. // increment (target, LUN) pair if valid on input
  541. //
  542. Dev = LSI_SCSI_FROM_PASS_THRU (This);
  543. if ((LastTarget > Dev->MaxTarget) || (*Lun > Dev->MaxLun)) {
  544. return EFI_INVALID_PARAMETER;
  545. }
  546. if (*Lun < Dev->MaxLun) {
  547. ++*Lun;
  548. return EFI_SUCCESS;
  549. }
  550. if (LastTarget < Dev->MaxTarget) {
  551. *Lun = 0;
  552. ++LastTarget;
  553. CopyMem (Target, &LastTarget, sizeof LastTarget);
  554. return EFI_SUCCESS;
  555. }
  556. return EFI_NOT_FOUND;
  557. }
  558. EFI_STATUS
  559. EFIAPI
  560. LsiScsiBuildDevicePath (
  561. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  562. IN UINT8 *Target,
  563. IN UINT64 Lun,
  564. IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
  565. )
  566. {
  567. UINT16 TargetValue;
  568. LSI_SCSI_DEV *Dev;
  569. SCSI_DEVICE_PATH *ScsiDevicePath;
  570. if (DevicePath == NULL) {
  571. return EFI_INVALID_PARAMETER;
  572. }
  573. CopyMem (&TargetValue, Target, sizeof TargetValue);
  574. Dev = LSI_SCSI_FROM_PASS_THRU (This);
  575. if ((TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun) || (Lun > 0xFFFF)) {
  576. return EFI_NOT_FOUND;
  577. }
  578. ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
  579. if (ScsiDevicePath == NULL) {
  580. return EFI_OUT_OF_RESOURCES;
  581. }
  582. ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
  583. ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
  584. ScsiDevicePath->Header.Length[0] = (UINT8)sizeof *ScsiDevicePath;
  585. ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof *ScsiDevicePath >> 8);
  586. ScsiDevicePath->Pun = TargetValue;
  587. ScsiDevicePath->Lun = (UINT16)Lun;
  588. *DevicePath = &ScsiDevicePath->Header;
  589. return EFI_SUCCESS;
  590. }
  591. EFI_STATUS
  592. EFIAPI
  593. LsiScsiGetTargetLun (
  594. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  595. IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  596. OUT UINT8 **TargetPointer,
  597. OUT UINT64 *Lun
  598. )
  599. {
  600. SCSI_DEVICE_PATH *ScsiDevicePath;
  601. LSI_SCSI_DEV *Dev;
  602. UINT8 *Target;
  603. if ((DevicePath == NULL) || (TargetPointer == NULL) || (*TargetPointer == NULL) ||
  604. (Lun == NULL))
  605. {
  606. return EFI_INVALID_PARAMETER;
  607. }
  608. if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
  609. (DevicePath->SubType != MSG_SCSI_DP))
  610. {
  611. return EFI_UNSUPPORTED;
  612. }
  613. ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
  614. Dev = LSI_SCSI_FROM_PASS_THRU (This);
  615. if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||
  616. (ScsiDevicePath->Lun > Dev->MaxLun))
  617. {
  618. return EFI_NOT_FOUND;
  619. }
  620. Target = *TargetPointer;
  621. ZeroMem (Target, TARGET_MAX_BYTES);
  622. CopyMem (Target, &ScsiDevicePath->Pun, sizeof ScsiDevicePath->Pun);
  623. *Lun = ScsiDevicePath->Lun;
  624. return EFI_SUCCESS;
  625. }
  626. EFI_STATUS
  627. EFIAPI
  628. LsiScsiResetChannel (
  629. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
  630. )
  631. {
  632. return EFI_UNSUPPORTED;
  633. }
  634. EFI_STATUS
  635. EFIAPI
  636. LsiScsiResetTargetLun (
  637. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  638. IN UINT8 *Target,
  639. IN UINT64 Lun
  640. )
  641. {
  642. return EFI_UNSUPPORTED;
  643. }
  644. EFI_STATUS
  645. EFIAPI
  646. LsiScsiGetNextTarget (
  647. IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
  648. IN OUT UINT8 **TargetPointer
  649. )
  650. {
  651. LSI_SCSI_DEV *Dev;
  652. UINTN Idx;
  653. UINT8 *Target;
  654. UINT16 LastTarget;
  655. //
  656. // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
  657. //
  658. Target = *TargetPointer;
  659. //
  660. // Search for first non-0xFF byte. If not found, return first target.
  661. //
  662. for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {
  663. }
  664. if (Idx == TARGET_MAX_BYTES) {
  665. SetMem (Target, TARGET_MAX_BYTES, 0x00);
  666. return EFI_SUCCESS;
  667. }
  668. CopyMem (&LastTarget, Target, sizeof LastTarget);
  669. //
  670. // increment target if valid on input
  671. //
  672. Dev = LSI_SCSI_FROM_PASS_THRU (This);
  673. if (LastTarget > Dev->MaxTarget) {
  674. return EFI_INVALID_PARAMETER;
  675. }
  676. if (LastTarget < Dev->MaxTarget) {
  677. ++LastTarget;
  678. CopyMem (Target, &LastTarget, sizeof LastTarget);
  679. return EFI_SUCCESS;
  680. }
  681. return EFI_NOT_FOUND;
  682. }
  683. STATIC
  684. VOID
  685. EFIAPI
  686. LsiScsiExitBoot (
  687. IN EFI_EVENT Event,
  688. IN VOID *Context
  689. )
  690. {
  691. LSI_SCSI_DEV *Dev;
  692. Dev = Context;
  693. DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
  694. LsiScsiReset (Dev);
  695. }
  696. //
  697. // Probe, start and stop functions of this driver, called by the DXE core for
  698. // specific devices.
  699. //
  700. // The following specifications document these interfaces:
  701. // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
  702. // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
  703. //
  704. EFI_STATUS
  705. EFIAPI
  706. LsiScsiControllerSupported (
  707. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  708. IN EFI_HANDLE ControllerHandle,
  709. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  710. )
  711. {
  712. EFI_STATUS Status;
  713. EFI_PCI_IO_PROTOCOL *PciIo;
  714. PCI_TYPE00 Pci;
  715. Status = gBS->OpenProtocol (
  716. ControllerHandle,
  717. &gEfiPciIoProtocolGuid,
  718. (VOID **)&PciIo,
  719. This->DriverBindingHandle,
  720. ControllerHandle,
  721. EFI_OPEN_PROTOCOL_BY_DRIVER
  722. );
  723. if (EFI_ERROR (Status)) {
  724. return Status;
  725. }
  726. Status = PciIo->Pci.Read (
  727. PciIo,
  728. EfiPciIoWidthUint32,
  729. 0,
  730. sizeof (Pci) / sizeof (UINT32),
  731. &Pci
  732. );
  733. if (EFI_ERROR (Status)) {
  734. goto Done;
  735. }
  736. if ((Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID) &&
  737. (Pci.Hdr.DeviceId == LSI_53C895A_PCI_DEVICE_ID))
  738. {
  739. Status = EFI_SUCCESS;
  740. } else {
  741. Status = EFI_UNSUPPORTED;
  742. }
  743. Done:
  744. gBS->CloseProtocol (
  745. ControllerHandle,
  746. &gEfiPciIoProtocolGuid,
  747. This->DriverBindingHandle,
  748. ControllerHandle
  749. );
  750. return Status;
  751. }
  752. EFI_STATUS
  753. EFIAPI
  754. LsiScsiControllerStart (
  755. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  756. IN EFI_HANDLE ControllerHandle,
  757. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  758. )
  759. {
  760. EFI_STATUS Status;
  761. LSI_SCSI_DEV *Dev;
  762. UINTN Pages;
  763. UINTN BytesMapped;
  764. Dev = AllocateZeroPool (sizeof (*Dev));
  765. if (Dev == NULL) {
  766. return EFI_OUT_OF_RESOURCES;
  767. }
  768. Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
  769. STATIC_ASSERT (
  770. FixedPcdGet8 (PcdLsiScsiMaxTargetLimit) < 8,
  771. "LSI 53C895A supports targets [0..7]"
  772. );
  773. STATIC_ASSERT (
  774. FixedPcdGet8 (PcdLsiScsiMaxLunLimit) < 128,
  775. "LSI 53C895A supports LUNs [0..127]"
  776. );
  777. Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
  778. Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
  779. Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
  780. Status = gBS->OpenProtocol (
  781. ControllerHandle,
  782. &gEfiPciIoProtocolGuid,
  783. (VOID **)&Dev->PciIo,
  784. This->DriverBindingHandle,
  785. ControllerHandle,
  786. EFI_OPEN_PROTOCOL_BY_DRIVER
  787. );
  788. if (EFI_ERROR (Status)) {
  789. goto FreePool;
  790. }
  791. Status = Dev->PciIo->Attributes (
  792. Dev->PciIo,
  793. EfiPciIoAttributeOperationGet,
  794. 0,
  795. &Dev->OrigPciAttrs
  796. );
  797. if (EFI_ERROR (Status)) {
  798. goto CloseProtocol;
  799. }
  800. //
  801. // Enable I/O Space & Bus-Mastering
  802. //
  803. Status = Dev->PciIo->Attributes (
  804. Dev->PciIo,
  805. EfiPciIoAttributeOperationEnable,
  806. (EFI_PCI_IO_ATTRIBUTE_IO |
  807. EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
  808. NULL
  809. );
  810. if (EFI_ERROR (Status)) {
  811. goto CloseProtocol;
  812. }
  813. //
  814. // Create buffers for data transfer
  815. //
  816. Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
  817. Status = Dev->PciIo->AllocateBuffer (
  818. Dev->PciIo,
  819. AllocateAnyPages,
  820. EfiBootServicesData,
  821. Pages,
  822. (VOID **)&Dev->Dma,
  823. EFI_PCI_ATTRIBUTE_MEMORY_CACHED
  824. );
  825. if (EFI_ERROR (Status)) {
  826. goto RestoreAttributes;
  827. }
  828. BytesMapped = EFI_PAGES_TO_SIZE (Pages);
  829. Status = Dev->PciIo->Map (
  830. Dev->PciIo,
  831. EfiPciIoOperationBusMasterCommonBuffer,
  832. Dev->Dma,
  833. &BytesMapped,
  834. &Dev->DmaPhysical,
  835. &Dev->DmaMapping
  836. );
  837. if (EFI_ERROR (Status)) {
  838. goto FreeBuffer;
  839. }
  840. if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
  841. Status = EFI_OUT_OF_RESOURCES;
  842. goto Unmap;
  843. }
  844. Status = LsiScsiReset (Dev);
  845. if (EFI_ERROR (Status)) {
  846. goto Unmap;
  847. }
  848. Status = gBS->CreateEvent (
  849. EVT_SIGNAL_EXIT_BOOT_SERVICES,
  850. TPL_CALLBACK,
  851. &LsiScsiExitBoot,
  852. Dev,
  853. &Dev->ExitBoot
  854. );
  855. if (EFI_ERROR (Status)) {
  856. goto UninitDev;
  857. }
  858. //
  859. // Host adapter channel, doesn't exist
  860. //
  861. Dev->PassThruMode.AdapterId = MAX_UINT32;
  862. Dev->PassThruMode.Attributes =
  863. EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
  864. EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
  865. Dev->PassThru.Mode = &Dev->PassThruMode;
  866. Dev->PassThru.PassThru = &LsiScsiPassThru;
  867. Dev->PassThru.GetNextTargetLun = &LsiScsiGetNextTargetLun;
  868. Dev->PassThru.BuildDevicePath = &LsiScsiBuildDevicePath;
  869. Dev->PassThru.GetTargetLun = &LsiScsiGetTargetLun;
  870. Dev->PassThru.ResetChannel = &LsiScsiResetChannel;
  871. Dev->PassThru.ResetTargetLun = &LsiScsiResetTargetLun;
  872. Dev->PassThru.GetNextTarget = &LsiScsiGetNextTarget;
  873. Status = gBS->InstallProtocolInterface (
  874. &ControllerHandle,
  875. &gEfiExtScsiPassThruProtocolGuid,
  876. EFI_NATIVE_INTERFACE,
  877. &Dev->PassThru
  878. );
  879. if (EFI_ERROR (Status)) {
  880. goto CloseExitBoot;
  881. }
  882. return EFI_SUCCESS;
  883. CloseExitBoot:
  884. gBS->CloseEvent (Dev->ExitBoot);
  885. UninitDev:
  886. LsiScsiReset (Dev);
  887. Unmap:
  888. Dev->PciIo->Unmap (
  889. Dev->PciIo,
  890. Dev->DmaMapping
  891. );
  892. FreeBuffer:
  893. Dev->PciIo->FreeBuffer (
  894. Dev->PciIo,
  895. Pages,
  896. Dev->Dma
  897. );
  898. RestoreAttributes:
  899. Dev->PciIo->Attributes (
  900. Dev->PciIo,
  901. EfiPciIoAttributeOperationSet,
  902. Dev->OrigPciAttrs,
  903. NULL
  904. );
  905. CloseProtocol:
  906. gBS->CloseProtocol (
  907. ControllerHandle,
  908. &gEfiPciIoProtocolGuid,
  909. This->DriverBindingHandle,
  910. ControllerHandle
  911. );
  912. FreePool:
  913. FreePool (Dev);
  914. return Status;
  915. }
  916. EFI_STATUS
  917. EFIAPI
  918. LsiScsiControllerStop (
  919. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  920. IN EFI_HANDLE ControllerHandle,
  921. IN UINTN NumberOfChildren,
  922. IN EFI_HANDLE *ChildHandleBuffer
  923. )
  924. {
  925. EFI_STATUS Status;
  926. EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
  927. LSI_SCSI_DEV *Dev;
  928. Status = gBS->OpenProtocol (
  929. ControllerHandle,
  930. &gEfiExtScsiPassThruProtocolGuid,
  931. (VOID **)&PassThru,
  932. This->DriverBindingHandle,
  933. ControllerHandle,
  934. EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
  935. );
  936. if (EFI_ERROR (Status)) {
  937. return Status;
  938. }
  939. Dev = LSI_SCSI_FROM_PASS_THRU (PassThru);
  940. Status = gBS->UninstallProtocolInterface (
  941. ControllerHandle,
  942. &gEfiExtScsiPassThruProtocolGuid,
  943. &Dev->PassThru
  944. );
  945. if (EFI_ERROR (Status)) {
  946. return Status;
  947. }
  948. gBS->CloseEvent (Dev->ExitBoot);
  949. LsiScsiReset (Dev);
  950. Dev->PciIo->Unmap (
  951. Dev->PciIo,
  952. Dev->DmaMapping
  953. );
  954. Dev->PciIo->FreeBuffer (
  955. Dev->PciIo,
  956. EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
  957. Dev->Dma
  958. );
  959. Dev->PciIo->Attributes (
  960. Dev->PciIo,
  961. EfiPciIoAttributeOperationSet,
  962. Dev->OrigPciAttrs,
  963. NULL
  964. );
  965. gBS->CloseProtocol (
  966. ControllerHandle,
  967. &gEfiPciIoProtocolGuid,
  968. This->DriverBindingHandle,
  969. ControllerHandle
  970. );
  971. FreePool (Dev);
  972. return Status;
  973. }
  974. //
  975. // The static object that groups the Supported() (ie. probe), Start() and
  976. // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
  977. // C, 10.1 EFI Driver Binding Protocol.
  978. //
  979. STATIC
  980. EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
  981. &LsiScsiControllerSupported,
  982. &LsiScsiControllerStart,
  983. &LsiScsiControllerStop,
  984. 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
  985. NULL, // ImageHandle, to be overwritten by
  986. // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
  987. NULL // DriverBindingHandle, ditto
  988. };
  989. //
  990. // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
  991. // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
  992. // in English, for display on standard console devices. This is recommended for
  993. // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
  994. // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
  995. //
  996. // Device type names ("LSI 53C895A SCSI Controller") are not formatted because
  997. // the driver supports only that device type. Therefore the driver name
  998. // suffices for unambiguous identification.
  999. //
  1000. STATIC
  1001. EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
  1002. { "eng;en", L"LSI 53C895A SCSI Controller Driver" },
  1003. { NULL, NULL }
  1004. };
  1005. STATIC
  1006. EFI_COMPONENT_NAME_PROTOCOL gComponentName;
  1007. EFI_STATUS
  1008. EFIAPI
  1009. LsiScsiGetDriverName (
  1010. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1011. IN CHAR8 *Language,
  1012. OUT CHAR16 **DriverName
  1013. )
  1014. {
  1015. return LookupUnicodeString2 (
  1016. Language,
  1017. This->SupportedLanguages,
  1018. mDriverNameTable,
  1019. DriverName,
  1020. (BOOLEAN)(This == &gComponentName) // Iso639Language
  1021. );
  1022. }
  1023. EFI_STATUS
  1024. EFIAPI
  1025. LsiScsiGetDeviceName (
  1026. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1027. IN EFI_HANDLE DeviceHandle,
  1028. IN EFI_HANDLE ChildHandle,
  1029. IN CHAR8 *Language,
  1030. OUT CHAR16 **ControllerName
  1031. )
  1032. {
  1033. return EFI_UNSUPPORTED;
  1034. }
  1035. STATIC
  1036. EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
  1037. &LsiScsiGetDriverName,
  1038. &LsiScsiGetDeviceName,
  1039. "eng" // SupportedLanguages, ISO 639-2 language codes
  1040. };
  1041. STATIC
  1042. EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
  1043. (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&LsiScsiGetDriverName,
  1044. (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&LsiScsiGetDeviceName,
  1045. "en" // SupportedLanguages, RFC 4646 language codes
  1046. };
  1047. //
  1048. // Entry point of this driver
  1049. //
  1050. EFI_STATUS
  1051. EFIAPI
  1052. LsiScsiEntryPoint (
  1053. IN EFI_HANDLE ImageHandle,
  1054. IN EFI_SYSTEM_TABLE *SystemTable
  1055. )
  1056. {
  1057. return EfiLibInstallDriverBindingComponentName2 (
  1058. ImageHandle,
  1059. SystemTable,
  1060. &gDriverBinding,
  1061. ImageHandle, // The handle to install onto
  1062. &gComponentName,
  1063. &gComponentName2
  1064. );
  1065. }