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