]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/MptScsiDxe/MptScsi.c
OvmfPkg/MptScsiDxe: Initialize hardware
[mirror_edk2.git] / OvmfPkg / MptScsiDxe / MptScsi.c
1 /** @file
2
3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 LSI Fusion MPT SCSI devices.
5
6 Copyright (C) 2020, Oracle and/or its affiliates.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <IndustryStandard/FusionMptScsi.h>
13 #include <IndustryStandard/Pci.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
20 #include <Protocol/PciIo.h>
21 #include <Protocol/ScsiPassThruExt.h>
22 #include <Uefi/UefiSpec.h>
23
24 //
25 // Higher versions will be used before lower, 0x10-0xffffffef is the version
26 // range for IVH (Indie Hardware Vendors)
27 //
28 #define MPT_SCSI_BINDING_VERSION 0x10
29
30 //
31 // Runtime Structures
32 //
33
34 #define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
35 typedef struct {
36 UINT32 Signature;
37 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
38 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;
39 UINT8 MaxTarget;
40 EFI_PCI_IO_PROTOCOL *PciIo;
41 UINT64 OriginalPciAttributes;
42 } MPT_SCSI_DEV;
43
44 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
45 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
46
47 //
48 // Hardware functions
49 //
50
51 STATIC
52 EFI_STATUS
53 Out32 (
54 IN MPT_SCSI_DEV *Dev,
55 IN UINT32 Addr,
56 IN UINT32 Data
57 )
58 {
59 return Dev->PciIo->Io.Write (
60 Dev->PciIo,
61 EfiPciIoWidthUint32,
62 PCI_BAR_IDX0,
63 Addr,
64 1,
65 &Data
66 );
67 }
68
69 STATIC
70 EFI_STATUS
71 In32 (
72 IN MPT_SCSI_DEV *Dev,
73 IN UINT32 Addr,
74 OUT UINT32 *Data
75 )
76 {
77 return Dev->PciIo->Io.Read (
78 Dev->PciIo,
79 EfiPciIoWidthUint32,
80 PCI_BAR_IDX0,
81 Addr,
82 1,
83 Data
84 );
85 }
86
87 STATIC
88 EFI_STATUS
89 MptDoorbell (
90 IN MPT_SCSI_DEV *Dev,
91 IN UINT8 DoorbellFunc,
92 IN UINT8 DoorbellArg
93 )
94 {
95 return Out32 (
96 Dev,
97 MPT_REG_DOORBELL,
98 (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)
99 );
100 }
101
102 STATIC
103 EFI_STATUS
104 MptScsiReset (
105 IN MPT_SCSI_DEV *Dev
106 )
107 {
108 EFI_STATUS Status;
109
110 //
111 // Reset hardware
112 //
113 Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);
114 if (EFI_ERROR (Status)) {
115 return Status;
116 }
117 //
118 // Mask interrupts
119 //
120 Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);
121 if (EFI_ERROR (Status)) {
122 return Status;
123 }
124 //
125 // Clear interrupt status
126 //
127 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
128 if (EFI_ERROR (Status)) {
129 return Status;
130 }
131
132 return EFI_SUCCESS;
133 }
134
135 STATIC
136 EFI_STATUS
137 MptScsiInit (
138 IN MPT_SCSI_DEV *Dev
139 )
140 {
141 EFI_STATUS Status;
142 union {
143 MPT_IO_CONTROLLER_INIT_REQUEST Data;
144 UINT32 Uint32;
145 } AlignedReq;
146 MPT_IO_CONTROLLER_INIT_REQUEST *Req;
147 MPT_IO_CONTROLLER_INIT_REPLY Reply;
148 UINT8 *ReplyBytes;
149 UINT32 ReplyWord;
150
151 Req = &AlignedReq.Data;
152
153 Status = MptScsiReset (Dev);
154 if (EFI_ERROR (Status)) {
155 return Status;
156 }
157
158 ZeroMem (Req, sizeof (*Req));
159 ZeroMem (&Reply, sizeof (Reply));
160 Req->WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;
161 Req->Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;
162 STATIC_ASSERT (
163 FixedPcdGet8 (PcdMptScsiMaxTargetLimit) < 255,
164 "Req supports 255 targets only (max target is 254)"
165 );
166 Req->MaxDevices = Dev->MaxTarget + 1;
167 Req->MaxBuses = 1;
168
169 //
170 // Send controller init through doorbell
171 //
172 STATIC_ASSERT (
173 sizeof (*Req) % sizeof (UINT32) == 0,
174 "Req must be multiple of UINT32"
175 );
176 STATIC_ASSERT (
177 sizeof (*Req) / sizeof (UINT32) <= MAX_UINT8,
178 "Req must fit in MAX_UINT8 Dwords"
179 );
180 Status = MptDoorbell (
181 Dev,
182 MPT_DOORBELL_HANDSHAKE,
183 (UINT8)(sizeof (*Req) / sizeof (UINT32))
184 );
185 if (EFI_ERROR (Status)) {
186 return Status;
187 }
188 Status = Dev->PciIo->Io.Write (
189 Dev->PciIo,
190 EfiPciIoWidthFifoUint32,
191 PCI_BAR_IDX0,
192 MPT_REG_DOORBELL,
193 sizeof (*Req) / sizeof (UINT32),
194 Req
195 );
196 if (EFI_ERROR (Status)) {
197 return Status;
198 }
199
200 //
201 // Read reply through doorbell
202 // Each 32bit (Dword) read produces 16bit (Word) of data
203 //
204 // The reply is read back to complete the doorbell function but it
205 // isn't useful because it doesn't contain relevant data or status
206 // codes.
207 //
208 STATIC_ASSERT (
209 sizeof (Reply) % sizeof (UINT16) == 0,
210 "Reply must be multiple of UINT16"
211 );
212 ReplyBytes = (UINT8 *)&Reply;
213 while (ReplyBytes != (UINT8 *)(&Reply + 1)) {
214 Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);
215 if (EFI_ERROR (Status)) {
216 return Status;
217 }
218 CopyMem (ReplyBytes, &ReplyWord, sizeof (UINT16));
219 ReplyBytes += sizeof (UINT16);
220 }
221
222 //
223 // Clear interrupts generated by doorbell reply
224 //
225 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
226 if (EFI_ERROR (Status)) {
227 return Status;
228 }
229
230 return EFI_SUCCESS;
231 }
232
233 //
234 // Ext SCSI Pass Thru
235 //
236
237 STATIC
238 EFI_STATUS
239 EFIAPI
240 MptScsiPassThru (
241 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
242 IN UINT8 *Target,
243 IN UINT64 Lun,
244 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
245 IN EFI_EVENT Event OPTIONAL
246 )
247 {
248 return EFI_UNSUPPORTED;
249 }
250
251 STATIC
252 BOOLEAN
253 IsTargetInitialized (
254 IN UINT8 *Target
255 )
256 {
257 UINTN Idx;
258
259 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
260 if (Target[Idx] != 0xFF) {
261 return TRUE;
262 }
263 }
264 return FALSE;
265 }
266
267 STATIC
268 EFI_STATUS
269 EFIAPI
270 MptScsiGetNextTargetLun (
271 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
272 IN OUT UINT8 **Target,
273 IN OUT UINT64 *Lun
274 )
275 {
276 MPT_SCSI_DEV *Dev;
277
278 Dev = MPT_SCSI_FROM_PASS_THRU (This);
279 //
280 // Currently support only LUN 0, so hardcode it
281 //
282 if (!IsTargetInitialized (*Target)) {
283 ZeroMem (*Target, TARGET_MAX_BYTES);
284 *Lun = 0;
285 } else if (**Target > Dev->MaxTarget || *Lun > 0) {
286 return EFI_INVALID_PARAMETER;
287 } else if (**Target < Dev->MaxTarget) {
288 //
289 // This device interface support 256 targets only, so it's enough to
290 // increment the LSB of Target, as it will never overflow.
291 //
292 **Target += 1;
293 } else {
294 return EFI_NOT_FOUND;
295 }
296
297 return EFI_SUCCESS;
298 }
299
300 STATIC
301 EFI_STATUS
302 EFIAPI
303 MptScsiGetNextTarget (
304 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
305 IN OUT UINT8 **Target
306 )
307 {
308 MPT_SCSI_DEV *Dev;
309
310 Dev = MPT_SCSI_FROM_PASS_THRU (This);
311 if (!IsTargetInitialized (*Target)) {
312 ZeroMem (*Target, TARGET_MAX_BYTES);
313 } else if (**Target > Dev->MaxTarget) {
314 return EFI_INVALID_PARAMETER;
315 } else if (**Target < Dev->MaxTarget) {
316 //
317 // This device interface support 256 targets only, so it's enough to
318 // increment the LSB of Target, as it will never overflow.
319 //
320 **Target += 1;
321 } else {
322 return EFI_NOT_FOUND;
323 }
324
325 return EFI_SUCCESS;
326 }
327
328 STATIC
329 EFI_STATUS
330 EFIAPI
331 MptScsiBuildDevicePath (
332 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
333 IN UINT8 *Target,
334 IN UINT64 Lun,
335 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
336 )
337 {
338 MPT_SCSI_DEV *Dev;
339 SCSI_DEVICE_PATH *ScsiDevicePath;
340
341 if (DevicePath == NULL) {
342 return EFI_INVALID_PARAMETER;
343 }
344
345 //
346 // This device support 256 targets only, so it's enough to dereference
347 // the LSB of Target.
348 //
349 Dev = MPT_SCSI_FROM_PASS_THRU (This);
350 if (*Target > Dev->MaxTarget || Lun > 0) {
351 return EFI_NOT_FOUND;
352 }
353
354 ScsiDevicePath = AllocateZeroPool (sizeof (*ScsiDevicePath));
355 if (ScsiDevicePath == NULL) {
356 return EFI_OUT_OF_RESOURCES;
357 }
358
359 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
360 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
361 ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);
362 ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);
363 ScsiDevicePath->Pun = *Target;
364 ScsiDevicePath->Lun = (UINT16)Lun;
365
366 *DevicePath = &ScsiDevicePath->Header;
367 return EFI_SUCCESS;
368 }
369
370 STATIC
371 EFI_STATUS
372 EFIAPI
373 MptScsiGetTargetLun (
374 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
375 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
376 OUT UINT8 **Target,
377 OUT UINT64 *Lun
378 )
379 {
380 MPT_SCSI_DEV *Dev;
381 SCSI_DEVICE_PATH *ScsiDevicePath;
382
383 if (DevicePath == NULL ||
384 Target == NULL || *Target == NULL || Lun == NULL) {
385 return EFI_INVALID_PARAMETER;
386 }
387
388 if (DevicePath->Type != MESSAGING_DEVICE_PATH ||
389 DevicePath->SubType != MSG_SCSI_DP) {
390 return EFI_UNSUPPORTED;
391 }
392
393 Dev = MPT_SCSI_FROM_PASS_THRU (This);
394 ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
395 if (ScsiDevicePath->Pun > Dev->MaxTarget ||
396 ScsiDevicePath->Lun > 0) {
397 return EFI_NOT_FOUND;
398 }
399
400 ZeroMem (*Target, TARGET_MAX_BYTES);
401 //
402 // This device support 256 targets only, so it's enough to set the LSB
403 // of Target.
404 //
405 **Target = (UINT8)ScsiDevicePath->Pun;
406 *Lun = ScsiDevicePath->Lun;
407
408 return EFI_SUCCESS;
409 }
410
411 STATIC
412 EFI_STATUS
413 EFIAPI
414 MptScsiResetChannel (
415 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
416 )
417 {
418 return EFI_UNSUPPORTED;
419 }
420
421 STATIC
422 EFI_STATUS
423 EFIAPI
424 MptScsiResetTargetLun (
425 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
426 IN UINT8 *Target,
427 IN UINT64 Lun
428 )
429 {
430 return EFI_UNSUPPORTED;
431 }
432
433 //
434 // Driver Binding
435 //
436
437 STATIC
438 EFI_STATUS
439 EFIAPI
440 MptScsiControllerSupported (
441 IN EFI_DRIVER_BINDING_PROTOCOL *This,
442 IN EFI_HANDLE ControllerHandle,
443 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
444 )
445 {
446 EFI_STATUS Status;
447 EFI_PCI_IO_PROTOCOL *PciIo;
448 PCI_TYPE00 Pci;
449
450 Status = gBS->OpenProtocol (
451 ControllerHandle,
452 &gEfiPciIoProtocolGuid,
453 (VOID **)&PciIo,
454 This->DriverBindingHandle,
455 ControllerHandle,
456 EFI_OPEN_PROTOCOL_BY_DRIVER
457 );
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461
462 Status = PciIo->Pci.Read (
463 PciIo,
464 EfiPciIoWidthUint32,
465 0,
466 sizeof (Pci) / sizeof (UINT32),
467 &Pci
468 );
469 if (EFI_ERROR (Status)) {
470 goto Done;
471 }
472
473 if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
474 (Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID ||
475 Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID ||
476 Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)) {
477 Status = EFI_SUCCESS;
478 } else {
479 Status = EFI_UNSUPPORTED;
480 }
481
482 Done:
483 gBS->CloseProtocol (
484 ControllerHandle,
485 &gEfiPciIoProtocolGuid,
486 This->DriverBindingHandle,
487 ControllerHandle
488 );
489 return Status;
490 }
491
492 STATIC
493 EFI_STATUS
494 EFIAPI
495 MptScsiControllerStart (
496 IN EFI_DRIVER_BINDING_PROTOCOL *This,
497 IN EFI_HANDLE ControllerHandle,
498 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
499 )
500 {
501 EFI_STATUS Status;
502 MPT_SCSI_DEV *Dev;
503
504 Dev = AllocateZeroPool (sizeof (*Dev));
505 if (Dev == NULL) {
506 return EFI_OUT_OF_RESOURCES;
507 }
508
509 Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
510
511 Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
512
513 Status = gBS->OpenProtocol (
514 ControllerHandle,
515 &gEfiPciIoProtocolGuid,
516 (VOID **)&Dev->PciIo,
517 This->DriverBindingHandle,
518 ControllerHandle,
519 EFI_OPEN_PROTOCOL_BY_DRIVER
520 );
521 if (EFI_ERROR (Status)) {
522 goto FreePool;
523 }
524
525 Status = Dev->PciIo->Attributes (
526 Dev->PciIo,
527 EfiPciIoAttributeOperationGet,
528 0,
529 &Dev->OriginalPciAttributes
530 );
531 if (EFI_ERROR (Status)) {
532 goto CloseProtocol;
533 }
534
535 //
536 // Enable I/O Space & Bus-Mastering
537 //
538 Status = Dev->PciIo->Attributes (
539 Dev->PciIo,
540 EfiPciIoAttributeOperationEnable,
541 (EFI_PCI_IO_ATTRIBUTE_IO |
542 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
543 NULL
544 );
545 if (EFI_ERROR (Status)) {
546 goto CloseProtocol;
547 }
548
549 //
550 // Signal device supports 64-bit DMA addresses
551 //
552 Status = Dev->PciIo->Attributes (
553 Dev->PciIo,
554 EfiPciIoAttributeOperationEnable,
555 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
556 NULL
557 );
558 if (EFI_ERROR (Status)) {
559 //
560 // Warn user that device will only be using 32-bit DMA addresses.
561 //
562 // Note that this does not prevent the device/driver from working
563 // and therefore we only warn and continue as usual.
564 //
565 DEBUG ((
566 DEBUG_WARN,
567 "%a: failed to enable 64-bit DMA addresses\n",
568 __FUNCTION__
569 ));
570 }
571
572 Status = MptScsiInit (Dev);
573 if (EFI_ERROR (Status)) {
574 goto RestoreAttributes;
575 }
576
577 //
578 // Host adapter channel, doesn't exist
579 //
580 Dev->PassThruMode.AdapterId = MAX_UINT32;
581 Dev->PassThruMode.Attributes =
582 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
583 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
584
585 Dev->PassThru.Mode = &Dev->PassThruMode;
586 Dev->PassThru.PassThru = &MptScsiPassThru;
587 Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;
588 Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;
589 Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;
590 Dev->PassThru.ResetChannel = &MptScsiResetChannel;
591 Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;
592 Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;
593
594 Status = gBS->InstallProtocolInterface (
595 &ControllerHandle,
596 &gEfiExtScsiPassThruProtocolGuid,
597 EFI_NATIVE_INTERFACE,
598 &Dev->PassThru
599 );
600 if (EFI_ERROR (Status)) {
601 goto UninitDev;
602 }
603
604 return EFI_SUCCESS;
605
606 UninitDev:
607 MptScsiReset (Dev);
608
609 RestoreAttributes:
610 Dev->PciIo->Attributes (
611 Dev->PciIo,
612 EfiPciIoAttributeOperationSet,
613 Dev->OriginalPciAttributes,
614 NULL
615 );
616
617 CloseProtocol:
618 gBS->CloseProtocol (
619 ControllerHandle,
620 &gEfiPciIoProtocolGuid,
621 This->DriverBindingHandle,
622 ControllerHandle
623 );
624
625 FreePool:
626 FreePool (Dev);
627
628 return Status;
629 }
630
631 STATIC
632 EFI_STATUS
633 EFIAPI
634 MptScsiControllerStop (
635 IN EFI_DRIVER_BINDING_PROTOCOL *This,
636 IN EFI_HANDLE ControllerHandle,
637 IN UINTN NumberOfChildren,
638 IN EFI_HANDLE *ChildHandleBuffer
639 )
640 {
641 EFI_STATUS Status;
642 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
643 MPT_SCSI_DEV *Dev;
644
645 Status = gBS->OpenProtocol (
646 ControllerHandle,
647 &gEfiExtScsiPassThruProtocolGuid,
648 (VOID **)&PassThru,
649 This->DriverBindingHandle,
650 ControllerHandle,
651 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
652 );
653 if (EFI_ERROR (Status)) {
654 return Status;
655 }
656
657 Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);
658
659 Status = gBS->UninstallProtocolInterface (
660 ControllerHandle,
661 &gEfiExtScsiPassThruProtocolGuid,
662 &Dev->PassThru
663 );
664 if (EFI_ERROR (Status)) {
665 return Status;
666 }
667
668 MptScsiReset (Dev);
669
670 Dev->PciIo->Attributes (
671 Dev->PciIo,
672 EfiPciIoAttributeOperationSet,
673 Dev->OriginalPciAttributes,
674 NULL
675 );
676
677 gBS->CloseProtocol (
678 ControllerHandle,
679 &gEfiPciIoProtocolGuid,
680 This->DriverBindingHandle,
681 ControllerHandle
682 );
683
684 FreePool (Dev);
685
686 return Status;
687 }
688
689 STATIC
690 EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {
691 &MptScsiControllerSupported,
692 &MptScsiControllerStart,
693 &MptScsiControllerStop,
694 MPT_SCSI_BINDING_VERSION,
695 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2
696 NULL, // DriverBindingHandle, filled as well
697 };
698
699 //
700 // Component Name
701 //
702
703 STATIC
704 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
705 { "eng;en", L"LSI Fusion MPT SCSI Driver" },
706 { NULL, NULL }
707 };
708
709 STATIC
710 EFI_COMPONENT_NAME_PROTOCOL mComponentName;
711
712 EFI_STATUS
713 EFIAPI
714 MptScsiGetDriverName (
715 IN EFI_COMPONENT_NAME_PROTOCOL *This,
716 IN CHAR8 *Language,
717 OUT CHAR16 **DriverName
718 )
719 {
720 return LookupUnicodeString2 (
721 Language,
722 This->SupportedLanguages,
723 mDriverNameTable,
724 DriverName,
725 (BOOLEAN)(This == &mComponentName) // Iso639Language
726 );
727 }
728
729 EFI_STATUS
730 EFIAPI
731 MptScsiGetDeviceName (
732 IN EFI_COMPONENT_NAME_PROTOCOL *This,
733 IN EFI_HANDLE DeviceHandle,
734 IN EFI_HANDLE ChildHandle,
735 IN CHAR8 *Language,
736 OUT CHAR16 **ControllerName
737 )
738 {
739 return EFI_UNSUPPORTED;
740 }
741
742 STATIC
743 EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
744 &MptScsiGetDriverName,
745 &MptScsiGetDeviceName,
746 "eng" // SupportedLanguages, ISO 639-2 language codes
747 };
748
749 STATIC
750 EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
751 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &MptScsiGetDriverName,
752 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &MptScsiGetDeviceName,
753 "en" // SupportedLanguages, RFC 4646 language codes
754 };
755
756 //
757 // Entry Point
758 //
759
760 EFI_STATUS
761 EFIAPI
762 MptScsiEntryPoint (
763 IN EFI_HANDLE ImageHandle,
764 IN EFI_SYSTEM_TABLE *SystemTable
765 )
766 {
767 return EfiLibInstallDriverBindingComponentName2 (
768 ImageHandle,
769 SystemTable,
770 &mMptScsiDriverBinding,
771 ImageHandle, // The handle to install onto
772 &mComponentName,
773 &mComponentName2
774 );
775 }