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