OvmfPkg/MptScsiDxe: Implement the PassThru method
[mirror_edk2.git] / OvmfPkg / MptScsiDxe / MptScsi.c
CommitLineData
feec20b2
NL
1/** @file\r
2\r
3 This driver produces Extended SCSI Pass Thru Protocol instances for\r
4 LSI Fusion MPT SCSI devices.\r
5\r
6 Copyright (C) 2020, Oracle and/or its affiliates.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
f4707442
NL
12#include <IndustryStandard/FusionMptScsi.h>\r
13#include <IndustryStandard/Pci.h>\r
505812ae 14#include <Library/BaseLib.h>\r
093cceaf 15#include <Library/BaseMemoryLib.h>\r
a53e5b41
NL
16#include <Library/DebugLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
093cceaf 18#include <Library/PcdLib.h>\r
f4707442 19#include <Library/UefiBootServicesTableLib.h>\r
ad8f2d6b 20#include <Library/UefiLib.h>\r
f4707442 21#include <Protocol/PciIo.h>\r
505812ae 22#include <Protocol/PciRootBridgeIo.h>\r
a53e5b41 23#include <Protocol/ScsiPassThruExt.h>\r
feec20b2
NL
24#include <Uefi/UefiSpec.h>\r
25\r
ad8f2d6b
NL
26//\r
27// Higher versions will be used before lower, 0x10-0xffffffef is the version\r
28// range for IVH (Indie Hardware Vendors)\r
29//\r
30#define MPT_SCSI_BINDING_VERSION 0x10\r
31\r
a53e5b41
NL
32//\r
33// Runtime Structures\r
34//\r
35\r
505812ae
NL
36typedef struct {\r
37 MPT_SCSI_REQUEST_ALIGNED IoRequest;\r
38 MPT_SCSI_IO_REPLY_ALIGNED IoReply;\r
39 //\r
40 // As EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.SenseDataLength is defined\r
41 // as UINT8, defining here SenseData size to MAX_UINT8 will guarantee it\r
42 // cannot overflow when passed to device.\r
43 //\r
44 UINT8 Sense[MAX_UINT8];\r
45 //\r
46 // This size of the data is arbitrarily chosen.\r
47 // It seems to be sufficient for all I/O requests sent through\r
48 // EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() for common boot scenarios.\r
49 //\r
50 UINT8 Data[0x2000];\r
51} MPT_SCSI_DMA_BUFFER;\r
52\r
a53e5b41
NL
53#define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')\r
54typedef struct {\r
55 UINT32 Signature;\r
56 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;\r
57 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;\r
093cceaf 58 UINT8 MaxTarget;\r
505812ae 59 UINT32 StallPerPollUsec;\r
da8c0b8f 60 EFI_PCI_IO_PROTOCOL *PciIo;\r
ecdbdba6 61 UINT64 OriginalPciAttributes;\r
505812ae
NL
62 MPT_SCSI_DMA_BUFFER *Dma;\r
63 EFI_PHYSICAL_ADDRESS DmaPhysical;\r
64 VOID *DmaMapping;\r
65 BOOLEAN IoReplyEnqueued;\r
a53e5b41
NL
66} MPT_SCSI_DEV;\r
67\r
68#define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \\r
69 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)\r
70\r
505812ae
NL
71#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \\r
72 (Dev->DmaPhysical + OFFSET_OF (MPT_SCSI_DMA_BUFFER, MemberName))\r
73\r
74#define MPT_SCSI_DMA_ADDR_HIGH(Dev, MemberName) \\r
75 ((UINT32)RShiftU64 (MPT_SCSI_DMA_ADDR (Dev, MemberName), 32))\r
76\r
77#define MPT_SCSI_DMA_ADDR_LOW(Dev, MemberName) \\r
78 ((UINT32)MPT_SCSI_DMA_ADDR (Dev, MemberName))\r
79\r
81cada98
NL
80//\r
81// Hardware functions\r
82//\r
83\r
84STATIC\r
85EFI_STATUS\r
86Out32 (\r
87 IN MPT_SCSI_DEV *Dev,\r
88 IN UINT32 Addr,\r
89 IN UINT32 Data\r
90 )\r
91{\r
92 return Dev->PciIo->Io.Write (\r
93 Dev->PciIo,\r
94 EfiPciIoWidthUint32,\r
95 PCI_BAR_IDX0,\r
96 Addr,\r
97 1,\r
98 &Data\r
99 );\r
100}\r
101\r
102STATIC\r
103EFI_STATUS\r
104In32 (\r
105 IN MPT_SCSI_DEV *Dev,\r
106 IN UINT32 Addr,\r
107 OUT UINT32 *Data\r
108 )\r
109{\r
110 return Dev->PciIo->Io.Read (\r
111 Dev->PciIo,\r
112 EfiPciIoWidthUint32,\r
113 PCI_BAR_IDX0,\r
114 Addr,\r
115 1,\r
116 Data\r
117 );\r
118}\r
119\r
120STATIC\r
121EFI_STATUS\r
122MptDoorbell (\r
123 IN MPT_SCSI_DEV *Dev,\r
124 IN UINT8 DoorbellFunc,\r
125 IN UINT8 DoorbellArg\r
126 )\r
127{\r
128 return Out32 (\r
129 Dev,\r
130 MPT_REG_DOORBELL,\r
131 (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)\r
132 );\r
133}\r
134\r
135STATIC\r
136EFI_STATUS\r
137MptScsiReset (\r
138 IN MPT_SCSI_DEV *Dev\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142\r
143 //\r
144 // Reset hardware\r
145 //\r
146 Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);\r
147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150 //\r
151 // Mask interrupts\r
152 //\r
153 Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);\r
154 if (EFI_ERROR (Status)) {\r
155 return Status;\r
156 }\r
157 //\r
158 // Clear interrupt status\r
159 //\r
160 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);\r
161 if (EFI_ERROR (Status)) {\r
162 return Status;\r
163 }\r
164\r
165 return EFI_SUCCESS;\r
166}\r
167\r
168STATIC\r
169EFI_STATUS\r
170MptScsiInit (\r
171 IN MPT_SCSI_DEV *Dev\r
172 )\r
173{\r
174 EFI_STATUS Status;\r
175 union {\r
176 MPT_IO_CONTROLLER_INIT_REQUEST Data;\r
177 UINT32 Uint32;\r
178 } AlignedReq;\r
179 MPT_IO_CONTROLLER_INIT_REQUEST *Req;\r
180 MPT_IO_CONTROLLER_INIT_REPLY Reply;\r
181 UINT8 *ReplyBytes;\r
182 UINT32 ReplyWord;\r
183\r
184 Req = &AlignedReq.Data;\r
185\r
186 Status = MptScsiReset (Dev);\r
187 if (EFI_ERROR (Status)) {\r
188 return Status;\r
189 }\r
190\r
191 ZeroMem (Req, sizeof (*Req));\r
192 ZeroMem (&Reply, sizeof (Reply));\r
193 Req->WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;\r
194 Req->Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;\r
195 STATIC_ASSERT (\r
196 FixedPcdGet8 (PcdMptScsiMaxTargetLimit) < 255,\r
197 "Req supports 255 targets only (max target is 254)"\r
198 );\r
199 Req->MaxDevices = Dev->MaxTarget + 1;\r
200 Req->MaxBuses = 1;\r
505812ae
NL
201 Req->ReplyFrameSize = sizeof Dev->Dma->IoReply.Data;\r
202 Req->HostMfaHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, IoRequest);\r
203 Req->SenseBufferHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, Sense);\r
81cada98
NL
204\r
205 //\r
206 // Send controller init through doorbell\r
207 //\r
208 STATIC_ASSERT (\r
209 sizeof (*Req) % sizeof (UINT32) == 0,\r
210 "Req must be multiple of UINT32"\r
211 );\r
212 STATIC_ASSERT (\r
213 sizeof (*Req) / sizeof (UINT32) <= MAX_UINT8,\r
214 "Req must fit in MAX_UINT8 Dwords"\r
215 );\r
216 Status = MptDoorbell (\r
217 Dev,\r
218 MPT_DOORBELL_HANDSHAKE,\r
219 (UINT8)(sizeof (*Req) / sizeof (UINT32))\r
220 );\r
221 if (EFI_ERROR (Status)) {\r
222 return Status;\r
223 }\r
224 Status = Dev->PciIo->Io.Write (\r
225 Dev->PciIo,\r
226 EfiPciIoWidthFifoUint32,\r
227 PCI_BAR_IDX0,\r
228 MPT_REG_DOORBELL,\r
229 sizeof (*Req) / sizeof (UINT32),\r
230 Req\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
233 return Status;\r
234 }\r
235\r
236 //\r
237 // Read reply through doorbell\r
238 // Each 32bit (Dword) read produces 16bit (Word) of data\r
239 //\r
240 // The reply is read back to complete the doorbell function but it\r
241 // isn't useful because it doesn't contain relevant data or status\r
242 // codes.\r
243 //\r
244 STATIC_ASSERT (\r
245 sizeof (Reply) % sizeof (UINT16) == 0,\r
246 "Reply must be multiple of UINT16"\r
247 );\r
248 ReplyBytes = (UINT8 *)&Reply;\r
249 while (ReplyBytes != (UINT8 *)(&Reply + 1)) {\r
250 Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);\r
251 if (EFI_ERROR (Status)) {\r
252 return Status;\r
253 }\r
254 CopyMem (ReplyBytes, &ReplyWord, sizeof (UINT16));\r
255 ReplyBytes += sizeof (UINT16);\r
256 }\r
257\r
258 //\r
259 // Clear interrupts generated by doorbell reply\r
260 //\r
261 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);\r
262 if (EFI_ERROR (Status)) {\r
263 return Status;\r
264 }\r
265\r
266 return EFI_SUCCESS;\r
267}\r
268\r
505812ae
NL
269STATIC\r
270EFI_STATUS\r
271ReportHostAdapterError (\r
272 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
273 )\r
274{\r
275 DEBUG ((DEBUG_ERROR, "%a: fatal error in scsi request\n", __FUNCTION__));\r
276 Packet->InTransferLength = 0;\r
277 Packet->OutTransferLength = 0;\r
278 Packet->SenseDataLength = 0;\r
279 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
280 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;\r
281 return EFI_DEVICE_ERROR;\r
282}\r
283\r
284STATIC\r
285EFI_STATUS\r
286ReportHostAdapterOverrunError (\r
287 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
288 )\r
289{\r
290 Packet->SenseDataLength = 0;\r
291 Packet->HostAdapterStatus =\r
292 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
293 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
294 return EFI_BAD_BUFFER_SIZE;\r
295}\r
296\r
297STATIC\r
298EFI_STATUS\r
299MptScsiPopulateRequest (\r
300 IN MPT_SCSI_DEV *Dev,\r
301 IN UINT8 Target,\r
302 IN UINT64 Lun,\r
303 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
304 )\r
305{\r
306 MPT_SCSI_REQUEST_WITH_SG *Request;\r
307\r
308 Request = &Dev->Dma->IoRequest.Data;\r
309\r
310 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||\r
311 (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||\r
312 Packet->CdbLength > sizeof (Request->Header.Cdb)) {\r
313 return EFI_UNSUPPORTED;\r
314 }\r
315\r
316 if (Target > Dev->MaxTarget || Lun > 0 ||\r
317 Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||\r
318 //\r
319 // Trying to receive, but destination pointer is NULL, or contradicting\r
320 // transfer direction\r
321 //\r
322 (Packet->InTransferLength > 0 &&\r
323 (Packet->InDataBuffer == NULL ||\r
324 Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE\r
325 )\r
326 ) ||\r
327\r
328 //\r
329 // Trying to send, but source pointer is NULL, or contradicting transfer\r
330 // direction\r
331 //\r
332 (Packet->OutTransferLength > 0 &&\r
333 (Packet->OutDataBuffer == NULL ||\r
334 Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ\r
335 )\r
336 )\r
337 ) {\r
338 return EFI_INVALID_PARAMETER;\r
339 }\r
340\r
341 if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {\r
342 Packet->InTransferLength = sizeof (Dev->Dma->Data);\r
343 return ReportHostAdapterOverrunError (Packet);\r
344 }\r
345 if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {\r
346 Packet->OutTransferLength = sizeof (Dev->Dma->Data);\r
347 return ReportHostAdapterOverrunError (Packet);\r
348 }\r
349\r
350 ZeroMem (Request, sizeof (*Request));\r
351 Request->Header.TargetId = Target;\r
352 //\r
353 // Only LUN 0 is currently supported, hence the cast is safe\r
354 //\r
355 Request->Header.Lun[1] = (UINT8)Lun;\r
356 Request->Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;\r
357 Request->Header.MessageContext = 1; // We handle one request at a time\r
358\r
359 Request->Header.CdbLength = Packet->CdbLength;\r
360 CopyMem (Request->Header.Cdb, Packet->Cdb, Packet->CdbLength);\r
361\r
362 //\r
363 // SenseDataLength is UINT8, Sense[] is MAX_UINT8, so we can't overflow\r
364 //\r
365 ZeroMem (Dev->Dma->Sense, Packet->SenseDataLength);\r
366 Request->Header.SenseBufferLength = Packet->SenseDataLength;\r
367 Request->Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR_LOW (Dev, Sense);\r
368\r
369 Request->Sg.EndOfList = 1;\r
370 Request->Sg.EndOfBuffer = 1;\r
371 Request->Sg.LastElement = 1;\r
372 Request->Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;\r
373 Request->Sg.Is64BitAddress = 1;\r
374 Request->Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);\r
375\r
376 //\r
377 // "MPT_SG_ENTRY_SIMPLE.Length" is a 24-bit quantity.\r
378 //\r
379 STATIC_ASSERT (\r
380 sizeof (Dev->Dma->Data) < SIZE_16MB,\r
381 "MPT_SCSI_DMA_BUFFER.Data must be smaller than 16MB"\r
382 );\r
383\r
384 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
385 Request->Header.DataLength = Packet->InTransferLength;\r
386 Request->Sg.Length = Packet->InTransferLength;\r
387 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;\r
388 } else {\r
389 Request->Header.DataLength = Packet->OutTransferLength;\r
390 Request->Sg.Length = Packet->OutTransferLength;\r
391 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;\r
392\r
393 CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);\r
394 Request->Sg.BufferContainsData = 1;\r
395 }\r
396\r
397 if (Request->Header.DataLength == 0) {\r
398 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;\r
399 }\r
400\r
401 return EFI_SUCCESS;\r
402}\r
403\r
404STATIC\r
405EFI_STATUS\r
406MptScsiSendRequest (\r
407 IN MPT_SCSI_DEV *Dev,\r
408 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
409 )\r
410{\r
411 EFI_STATUS Status;\r
412\r
413 if (!Dev->IoReplyEnqueued) {\r
414 //\r
415 // Put one free reply frame on the reply queue, the hardware may use it to\r
416 // report an error to us.\r
417 //\r
418 Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoReply));\r
419 if (EFI_ERROR (Status)) {\r
420 return EFI_DEVICE_ERROR;\r
421 }\r
422 Dev->IoReplyEnqueued = TRUE;\r
423 }\r
424\r
425 Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoRequest));\r
426 if (EFI_ERROR (Status)) {\r
427 return EFI_DEVICE_ERROR;\r
428 }\r
429\r
430 return EFI_SUCCESS;\r
431}\r
432\r
433STATIC\r
434EFI_STATUS\r
435MptScsiGetReply (\r
436 IN MPT_SCSI_DEV *Dev,\r
437 OUT UINT32 *Reply\r
438 )\r
439{\r
440 EFI_STATUS Status;\r
441 UINT32 Istatus;\r
442 UINT32 EmptyReply;\r
443\r
444 //\r
445 // Timeouts are not supported for\r
446 // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() in this implementation.\r
447 //\r
448 for (;;) {\r
449 Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);\r
450 if (EFI_ERROR (Status)) {\r
451 return Status;\r
452 }\r
453\r
454 //\r
455 // Interrupt raised\r
456 //\r
457 if (Istatus & MPT_IMASK_REPLY) {\r
458 break;\r
459 }\r
460\r
461 gBS->Stall (Dev->StallPerPollUsec);\r
462 }\r
463\r
464 Status = In32 (Dev, MPT_REG_REP_Q, Reply);\r
465 if (EFI_ERROR (Status)) {\r
466 return Status;\r
467 }\r
468\r
469 //\r
470 // The driver is supposed to fetch replies until 0xffffffff is returned, which\r
471 // will reset the interrupt status. We put only one request, so we expect the\r
472 // next read reply to be the last.\r
473 //\r
474 Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);\r
475 if (EFI_ERROR (Status) || EmptyReply != MAX_UINT32) {\r
476 return EFI_DEVICE_ERROR;\r
477 }\r
478\r
479 return EFI_SUCCESS;\r
480}\r
481\r
482STATIC\r
483EFI_STATUS\r
484MptScsiHandleReply (\r
485 IN MPT_SCSI_DEV *Dev,\r
486 IN UINT32 Reply,\r
487 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
488 )\r
489{\r
490 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
491 CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);\r
492 }\r
493\r
494 if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {\r
495 //\r
496 // This is a turbo reply, everything is good\r
497 //\r
498 Packet->SenseDataLength = 0;\r
499 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
500 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
501\r
502 } else if ((Reply & BIT31) != 0) {\r
503 DEBUG ((DEBUG_INFO, "%a: Full reply returned\n", __FUNCTION__));\r
504 //\r
505 // When reply MSB is set, we got a full reply. Since we submitted only one\r
506 // reply frame, we know it's IoReply.\r
507 //\r
508 Dev->IoReplyEnqueued = FALSE;\r
509\r
510 Packet->TargetStatus = Dev->Dma->IoReply.Data.ScsiStatus;\r
511 //\r
512 // Make sure device only lowers SenseDataLength before copying sense\r
513 //\r
514 ASSERT (Dev->Dma->IoReply.Data.SenseCount <= Packet->SenseDataLength);\r
515 Packet->SenseDataLength =\r
516 (UINT8)MIN (Dev->Dma->IoReply.Data.SenseCount, Packet->SenseDataLength);\r
517 CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);\r
518\r
519 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
520 Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;\r
521 } else {\r
522 Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;\r
523 }\r
524\r
525 switch (Dev->Dma->IoReply.Data.IocStatus) {\r
526 case MPT_SCSI_IOCSTATUS_SUCCESS:\r
527 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
528 break;\r
529 case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:\r
530 Packet->HostAdapterStatus =\r
531 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;\r
532 return EFI_TIMEOUT;\r
533 case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:\r
534 case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:\r
535 Packet->HostAdapterStatus =\r
536 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
537 break;\r
538 default:\r
539 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
540 return EFI_DEVICE_ERROR;\r
541 }\r
542\r
543 } else {\r
544 DEBUG ((DEBUG_ERROR, "%a: unexpected reply (%x)\n", __FUNCTION__, Reply));\r
545 return ReportHostAdapterError (Packet);\r
546 }\r
547\r
548 return EFI_SUCCESS;\r
549}\r
550\r
a53e5b41
NL
551//\r
552// Ext SCSI Pass Thru\r
553//\r
554\r
555STATIC\r
556EFI_STATUS\r
557EFIAPI\r
558MptScsiPassThru (\r
559 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
560 IN UINT8 *Target,\r
561 IN UINT64 Lun,\r
562 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
563 IN EFI_EVENT Event OPTIONAL\r
564 )\r
565{\r
505812ae
NL
566 EFI_STATUS Status;\r
567 MPT_SCSI_DEV *Dev;\r
568 UINT32 Reply;\r
569\r
570 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
571 //\r
572 // We only use first byte of target identifer\r
573 //\r
574 Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);\r
575 if (EFI_ERROR (Status)) {\r
576 //\r
577 // MptScsiPopulateRequest modified packet according to the error\r
578 //\r
579 return Status;\r
580 }\r
581\r
582 Status = MptScsiSendRequest (Dev, Packet);\r
583 if (EFI_ERROR (Status)) {\r
584 return ReportHostAdapterError (Packet);\r
585 }\r
586\r
587 Status = MptScsiGetReply (Dev, &Reply);\r
588 if (EFI_ERROR (Status)) {\r
589 return ReportHostAdapterError (Packet);\r
590 }\r
591\r
592 return MptScsiHandleReply (Dev, Reply, Packet);\r
a53e5b41
NL
593}\r
594\r
093cceaf
NL
595STATIC\r
596BOOLEAN\r
597IsTargetInitialized (\r
598 IN UINT8 *Target\r
599 )\r
600{\r
601 UINTN Idx;\r
602\r
603 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {\r
604 if (Target[Idx] != 0xFF) {\r
605 return TRUE;\r
606 }\r
607 }\r
608 return FALSE;\r
609}\r
610\r
a53e5b41
NL
611STATIC\r
612EFI_STATUS\r
613EFIAPI\r
614MptScsiGetNextTargetLun (\r
615 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
616 IN OUT UINT8 **Target,\r
617 IN OUT UINT64 *Lun\r
618 )\r
619{\r
093cceaf
NL
620 MPT_SCSI_DEV *Dev;\r
621\r
622 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
623 //\r
624 // Currently support only LUN 0, so hardcode it\r
625 //\r
626 if (!IsTargetInitialized (*Target)) {\r
627 ZeroMem (*Target, TARGET_MAX_BYTES);\r
628 *Lun = 0;\r
629 } else if (**Target > Dev->MaxTarget || *Lun > 0) {\r
630 return EFI_INVALID_PARAMETER;\r
631 } else if (**Target < Dev->MaxTarget) {\r
632 //\r
633 // This device interface support 256 targets only, so it's enough to\r
634 // increment the LSB of Target, as it will never overflow.\r
635 //\r
636 **Target += 1;\r
637 } else {\r
638 return EFI_NOT_FOUND;\r
639 }\r
640\r
641 return EFI_SUCCESS;\r
a53e5b41
NL
642}\r
643\r
644STATIC\r
645EFI_STATUS\r
646EFIAPI\r
647MptScsiGetNextTarget (\r
648 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
649 IN OUT UINT8 **Target\r
650 )\r
651{\r
093cceaf
NL
652 MPT_SCSI_DEV *Dev;\r
653\r
654 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
655 if (!IsTargetInitialized (*Target)) {\r
656 ZeroMem (*Target, TARGET_MAX_BYTES);\r
657 } else if (**Target > Dev->MaxTarget) {\r
658 return EFI_INVALID_PARAMETER;\r
659 } else if (**Target < Dev->MaxTarget) {\r
660 //\r
661 // This device interface support 256 targets only, so it's enough to\r
662 // increment the LSB of Target, as it will never overflow.\r
663 //\r
664 **Target += 1;\r
665 } else {\r
666 return EFI_NOT_FOUND;\r
667 }\r
668\r
669 return EFI_SUCCESS;\r
a53e5b41
NL
670}\r
671\r
672STATIC\r
673EFI_STATUS\r
674EFIAPI\r
675MptScsiBuildDevicePath (\r
676 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
677 IN UINT8 *Target,\r
678 IN UINT64 Lun,\r
679 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
680 )\r
681{\r
f9941d31
NL
682 MPT_SCSI_DEV *Dev;\r
683 SCSI_DEVICE_PATH *ScsiDevicePath;\r
684\r
685 if (DevicePath == NULL) {\r
686 return EFI_INVALID_PARAMETER;\r
687 }\r
688\r
689 //\r
690 // This device support 256 targets only, so it's enough to dereference\r
691 // the LSB of Target.\r
692 //\r
693 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
694 if (*Target > Dev->MaxTarget || Lun > 0) {\r
695 return EFI_NOT_FOUND;\r
696 }\r
697\r
698 ScsiDevicePath = AllocateZeroPool (sizeof (*ScsiDevicePath));\r
699 if (ScsiDevicePath == NULL) {\r
700 return EFI_OUT_OF_RESOURCES;\r
701 }\r
702\r
703 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;\r
704 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;\r
705 ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);\r
706 ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);\r
707 ScsiDevicePath->Pun = *Target;\r
708 ScsiDevicePath->Lun = (UINT16)Lun;\r
709\r
710 *DevicePath = &ScsiDevicePath->Header;\r
711 return EFI_SUCCESS;\r
a53e5b41
NL
712}\r
713\r
714STATIC\r
715EFI_STATUS\r
716EFIAPI\r
717MptScsiGetTargetLun (\r
718 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
719 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
720 OUT UINT8 **Target,\r
721 OUT UINT64 *Lun\r
722 )\r
723{\r
f9941d31
NL
724 MPT_SCSI_DEV *Dev;\r
725 SCSI_DEVICE_PATH *ScsiDevicePath;\r
726\r
727 if (DevicePath == NULL ||\r
728 Target == NULL || *Target == NULL || Lun == NULL) {\r
729 return EFI_INVALID_PARAMETER;\r
730 }\r
731\r
732 if (DevicePath->Type != MESSAGING_DEVICE_PATH ||\r
733 DevicePath->SubType != MSG_SCSI_DP) {\r
734 return EFI_UNSUPPORTED;\r
735 }\r
736\r
737 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
738 ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;\r
739 if (ScsiDevicePath->Pun > Dev->MaxTarget ||\r
740 ScsiDevicePath->Lun > 0) {\r
741 return EFI_NOT_FOUND;\r
742 }\r
743\r
744 ZeroMem (*Target, TARGET_MAX_BYTES);\r
745 //\r
746 // This device support 256 targets only, so it's enough to set the LSB\r
747 // of Target.\r
748 //\r
749 **Target = (UINT8)ScsiDevicePath->Pun;\r
750 *Lun = ScsiDevicePath->Lun;\r
751\r
752 return EFI_SUCCESS;\r
a53e5b41
NL
753}\r
754\r
755STATIC\r
756EFI_STATUS\r
757EFIAPI\r
758MptScsiResetChannel (\r
759 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
760 )\r
761{\r
762 return EFI_UNSUPPORTED;\r
763}\r
764\r
765STATIC\r
766EFI_STATUS\r
767EFIAPI\r
768MptScsiResetTargetLun (\r
769 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
770 IN UINT8 *Target,\r
771 IN UINT64 Lun\r
772 )\r
773{\r
774 return EFI_UNSUPPORTED;\r
775}\r
776\r
ad8f2d6b
NL
777//\r
778// Driver Binding\r
779//\r
780\r
781STATIC\r
782EFI_STATUS\r
783EFIAPI\r
784MptScsiControllerSupported (\r
785 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
786 IN EFI_HANDLE ControllerHandle,\r
787 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
788 )\r
789{\r
f4707442
NL
790 EFI_STATUS Status;\r
791 EFI_PCI_IO_PROTOCOL *PciIo;\r
792 PCI_TYPE00 Pci;\r
793\r
794 Status = gBS->OpenProtocol (\r
795 ControllerHandle,\r
796 &gEfiPciIoProtocolGuid,\r
797 (VOID **)&PciIo,\r
798 This->DriverBindingHandle,\r
799 ControllerHandle,\r
800 EFI_OPEN_PROTOCOL_BY_DRIVER\r
801 );\r
802 if (EFI_ERROR (Status)) {\r
803 return Status;\r
804 }\r
805\r
806 Status = PciIo->Pci.Read (\r
807 PciIo,\r
808 EfiPciIoWidthUint32,\r
809 0,\r
810 sizeof (Pci) / sizeof (UINT32),\r
811 &Pci\r
812 );\r
813 if (EFI_ERROR (Status)) {\r
814 goto Done;\r
815 }\r
816\r
817 if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&\r
818 (Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID ||\r
819 Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID ||\r
820 Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)) {\r
821 Status = EFI_SUCCESS;\r
822 } else {\r
823 Status = EFI_UNSUPPORTED;\r
824 }\r
825\r
826Done:\r
827 gBS->CloseProtocol (\r
828 ControllerHandle,\r
829 &gEfiPciIoProtocolGuid,\r
830 This->DriverBindingHandle,\r
831 ControllerHandle\r
832 );\r
833 return Status;\r
ad8f2d6b
NL
834}\r
835\r
836STATIC\r
837EFI_STATUS\r
838EFIAPI\r
839MptScsiControllerStart (\r
840 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
841 IN EFI_HANDLE ControllerHandle,\r
842 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
843 )\r
844{\r
a53e5b41
NL
845 EFI_STATUS Status;\r
846 MPT_SCSI_DEV *Dev;\r
505812ae
NL
847 UINTN Pages;\r
848 UINTN BytesMapped;\r
a53e5b41
NL
849\r
850 Dev = AllocateZeroPool (sizeof (*Dev));\r
851 if (Dev == NULL) {\r
852 return EFI_OUT_OF_RESOURCES;\r
853 }\r
854\r
855 Dev->Signature = MPT_SCSI_DEV_SIGNATURE;\r
856\r
093cceaf 857 Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);\r
505812ae 858 Dev->StallPerPollUsec = PcdGet32 (PcdMptScsiStallPerPollUsec);\r
093cceaf 859\r
da8c0b8f
NL
860 Status = gBS->OpenProtocol (\r
861 ControllerHandle,\r
862 &gEfiPciIoProtocolGuid,\r
863 (VOID **)&Dev->PciIo,\r
864 This->DriverBindingHandle,\r
865 ControllerHandle,\r
866 EFI_OPEN_PROTOCOL_BY_DRIVER\r
867 );\r
868 if (EFI_ERROR (Status)) {\r
869 goto FreePool;\r
870 }\r
871\r
ecdbdba6
NL
872 Status = Dev->PciIo->Attributes (\r
873 Dev->PciIo,\r
874 EfiPciIoAttributeOperationGet,\r
875 0,\r
876 &Dev->OriginalPciAttributes\r
877 );\r
878 if (EFI_ERROR (Status)) {\r
879 goto CloseProtocol;\r
880 }\r
881\r
882 //\r
883 // Enable I/O Space & Bus-Mastering\r
884 //\r
885 Status = Dev->PciIo->Attributes (\r
886 Dev->PciIo,\r
887 EfiPciIoAttributeOperationEnable,\r
888 (EFI_PCI_IO_ATTRIBUTE_IO |\r
889 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
890 NULL\r
891 );\r
892 if (EFI_ERROR (Status)) {\r
893 goto CloseProtocol;\r
894 }\r
895\r
896 //\r
897 // Signal device supports 64-bit DMA addresses\r
898 //\r
899 Status = Dev->PciIo->Attributes (\r
900 Dev->PciIo,\r
901 EfiPciIoAttributeOperationEnable,\r
902 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
903 NULL\r
904 );\r
905 if (EFI_ERROR (Status)) {\r
906 //\r
907 // Warn user that device will only be using 32-bit DMA addresses.\r
908 //\r
909 // Note that this does not prevent the device/driver from working\r
910 // and therefore we only warn and continue as usual.\r
911 //\r
912 DEBUG ((\r
913 DEBUG_WARN,\r
914 "%a: failed to enable 64-bit DMA addresses\n",\r
915 __FUNCTION__\r
916 ));\r
917 }\r
918\r
505812ae
NL
919 //\r
920 // Create buffers for data transfer\r
921 //\r
922 Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));\r
923 Status = Dev->PciIo->AllocateBuffer (\r
924 Dev->PciIo,\r
925 AllocateAnyPages,\r
926 EfiBootServicesData,\r
927 Pages,\r
928 (VOID **)&Dev->Dma,\r
929 EFI_PCI_ATTRIBUTE_MEMORY_CACHED\r
930 );\r
81cada98
NL
931 if (EFI_ERROR (Status)) {\r
932 goto RestoreAttributes;\r
933 }\r
934\r
505812ae
NL
935 BytesMapped = EFI_PAGES_TO_SIZE (Pages);\r
936 Status = Dev->PciIo->Map (\r
937 Dev->PciIo,\r
938 EfiPciIoOperationBusMasterCommonBuffer,\r
939 Dev->Dma,\r
940 &BytesMapped,\r
941 &Dev->DmaPhysical,\r
942 &Dev->DmaMapping\r
943 );\r
944 if (EFI_ERROR (Status)) {\r
945 goto FreeBuffer;\r
946 }\r
947\r
948 if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {\r
949 Status = EFI_OUT_OF_RESOURCES;\r
950 goto Unmap;\r
951 }\r
952\r
953 Status = MptScsiInit (Dev);\r
954 if (EFI_ERROR (Status)) {\r
955 goto Unmap;\r
956 }\r
957\r
a53e5b41
NL
958 //\r
959 // Host adapter channel, doesn't exist\r
960 //\r
961 Dev->PassThruMode.AdapterId = MAX_UINT32;\r
962 Dev->PassThruMode.Attributes =\r
963 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
964 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
965\r
966 Dev->PassThru.Mode = &Dev->PassThruMode;\r
967 Dev->PassThru.PassThru = &MptScsiPassThru;\r
968 Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;\r
969 Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;\r
970 Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;\r
971 Dev->PassThru.ResetChannel = &MptScsiResetChannel;\r
972 Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;\r
973 Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;\r
974\r
975 Status = gBS->InstallProtocolInterface (\r
976 &ControllerHandle,\r
977 &gEfiExtScsiPassThruProtocolGuid,\r
978 EFI_NATIVE_INTERFACE,\r
979 &Dev->PassThru\r
980 );\r
981 if (EFI_ERROR (Status)) {\r
81cada98 982 goto UninitDev;\r
a53e5b41
NL
983 }\r
984\r
985 return EFI_SUCCESS;\r
986\r
81cada98
NL
987UninitDev:\r
988 MptScsiReset (Dev);\r
989\r
505812ae
NL
990Unmap:\r
991 Dev->PciIo->Unmap (\r
992 Dev->PciIo,\r
993 Dev->DmaMapping\r
994 );\r
995\r
996FreeBuffer:\r
997 Dev->PciIo->FreeBuffer (\r
998 Dev->PciIo,\r
999 Pages,\r
1000 Dev->Dma\r
1001 );\r
1002\r
ecdbdba6
NL
1003RestoreAttributes:\r
1004 Dev->PciIo->Attributes (\r
1005 Dev->PciIo,\r
1006 EfiPciIoAttributeOperationSet,\r
1007 Dev->OriginalPciAttributes,\r
1008 NULL\r
1009 );\r
1010\r
da8c0b8f
NL
1011CloseProtocol:\r
1012 gBS->CloseProtocol (\r
1013 ControllerHandle,\r
1014 &gEfiPciIoProtocolGuid,\r
1015 This->DriverBindingHandle,\r
1016 ControllerHandle\r
1017 );\r
1018\r
a53e5b41
NL
1019FreePool:\r
1020 FreePool (Dev);\r
1021\r
1022 return Status;\r
ad8f2d6b
NL
1023}\r
1024\r
1025STATIC\r
1026EFI_STATUS\r
1027EFIAPI\r
1028MptScsiControllerStop (\r
1029 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1030 IN EFI_HANDLE ControllerHandle,\r
1031 IN UINTN NumberOfChildren,\r
1032 IN EFI_HANDLE *ChildHandleBuffer\r
1033 )\r
1034{\r
a53e5b41
NL
1035 EFI_STATUS Status;\r
1036 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
1037 MPT_SCSI_DEV *Dev;\r
1038\r
1039 Status = gBS->OpenProtocol (\r
1040 ControllerHandle,\r
1041 &gEfiExtScsiPassThruProtocolGuid,\r
1042 (VOID **)&PassThru,\r
1043 This->DriverBindingHandle,\r
1044 ControllerHandle,\r
1045 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only\r
1046 );\r
1047 if (EFI_ERROR (Status)) {\r
1048 return Status;\r
1049 }\r
1050\r
1051 Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);\r
1052\r
1053 Status = gBS->UninstallProtocolInterface (\r
1054 ControllerHandle,\r
1055 &gEfiExtScsiPassThruProtocolGuid,\r
1056 &Dev->PassThru\r
1057 );\r
1058 if (EFI_ERROR (Status)) {\r
1059 return Status;\r
1060 }\r
1061\r
81cada98
NL
1062 MptScsiReset (Dev);\r
1063\r
505812ae
NL
1064 Dev->PciIo->Unmap (\r
1065 Dev->PciIo,\r
1066 Dev->DmaMapping\r
1067 );\r
1068\r
1069 Dev->PciIo->FreeBuffer (\r
1070 Dev->PciIo,\r
1071 EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),\r
1072 Dev->Dma\r
1073 );\r
1074\r
ecdbdba6
NL
1075 Dev->PciIo->Attributes (\r
1076 Dev->PciIo,\r
1077 EfiPciIoAttributeOperationSet,\r
1078 Dev->OriginalPciAttributes,\r
1079 NULL\r
1080 );\r
1081\r
da8c0b8f
NL
1082 gBS->CloseProtocol (\r
1083 ControllerHandle,\r
1084 &gEfiPciIoProtocolGuid,\r
1085 This->DriverBindingHandle,\r
1086 ControllerHandle\r
1087 );\r
1088\r
a53e5b41
NL
1089 FreePool (Dev);\r
1090\r
1091 return Status;\r
ad8f2d6b
NL
1092}\r
1093\r
1094STATIC\r
1095EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {\r
1096 &MptScsiControllerSupported,\r
1097 &MptScsiControllerStart,\r
1098 &MptScsiControllerStop,\r
1099 MPT_SCSI_BINDING_VERSION,\r
1100 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2\r
1101 NULL, // DriverBindingHandle, filled as well\r
1102};\r
1103\r
be7fcaa1
NL
1104//\r
1105// Component Name\r
1106//\r
1107\r
1108STATIC\r
1109EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
1110 { "eng;en", L"LSI Fusion MPT SCSI Driver" },\r
1111 { NULL, NULL }\r
1112};\r
1113\r
1114STATIC\r
1115EFI_COMPONENT_NAME_PROTOCOL mComponentName;\r
1116\r
1117EFI_STATUS\r
1118EFIAPI\r
1119MptScsiGetDriverName (\r
1120 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
1121 IN CHAR8 *Language,\r
1122 OUT CHAR16 **DriverName\r
1123 )\r
1124{\r
1125 return LookupUnicodeString2 (\r
1126 Language,\r
1127 This->SupportedLanguages,\r
1128 mDriverNameTable,\r
1129 DriverName,\r
1130 (BOOLEAN)(This == &mComponentName) // Iso639Language\r
1131 );\r
1132}\r
1133\r
1134EFI_STATUS\r
1135EFIAPI\r
1136MptScsiGetDeviceName (\r
1137 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
1138 IN EFI_HANDLE DeviceHandle,\r
1139 IN EFI_HANDLE ChildHandle,\r
1140 IN CHAR8 *Language,\r
1141 OUT CHAR16 **ControllerName\r
1142 )\r
1143{\r
1144 return EFI_UNSUPPORTED;\r
1145}\r
1146\r
1147STATIC\r
1148EFI_COMPONENT_NAME_PROTOCOL mComponentName = {\r
1149 &MptScsiGetDriverName,\r
1150 &MptScsiGetDeviceName,\r
1151 "eng" // SupportedLanguages, ISO 639-2 language codes\r
1152};\r
1153\r
1154STATIC\r
1155EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {\r
1156 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &MptScsiGetDriverName,\r
1157 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &MptScsiGetDeviceName,\r
1158 "en" // SupportedLanguages, RFC 4646 language codes\r
1159};\r
1160\r
feec20b2
NL
1161//\r
1162// Entry Point\r
1163//\r
1164\r
1165EFI_STATUS\r
1166EFIAPI\r
1167MptScsiEntryPoint (\r
1168 IN EFI_HANDLE ImageHandle,\r
1169 IN EFI_SYSTEM_TABLE *SystemTable\r
1170 )\r
1171{\r
ad8f2d6b
NL
1172 return EfiLibInstallDriverBindingComponentName2 (\r
1173 ImageHandle,\r
1174 SystemTable,\r
1175 &mMptScsiDriverBinding,\r
1176 ImageHandle, // The handle to install onto\r
be7fcaa1
NL
1177 &mComponentName,\r
1178 &mComponentName2\r
ad8f2d6b 1179 );\r
feec20b2 1180}\r