]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PvScsiDxe/PvScsi.c
OvmfPkg/PvScsiDxe: Reset adapter on init
[mirror_edk2.git] / OvmfPkg / PvScsiDxe / PvScsi.c
CommitLineData
478c07d4
LA
1/** @file\r
2\r
3 This driver produces Extended SCSI Pass Thru Protocol instances for\r
4 pvscsi 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
a9f9d5cf
LA
12#include <IndustryStandard/Pci.h>\r
13#include <IndustryStandard/PvScsi.h>\r
7efce2e5 14#include <Library/BaseMemoryLib.h>\r
e497432c 15#include <Library/MemoryAllocationLib.h>\r
a9f9d5cf 16#include <Library/UefiBootServicesTableLib.h>\r
ed08c571 17#include <Library/UefiLib.h>\r
a9f9d5cf 18#include <Protocol/PciIo.h>\r
478c07d4
LA
19#include <Uefi/UefiSpec.h>\r
20\r
e497432c
LA
21#include "PvScsi.h"\r
22\r
ed08c571
LA
23//\r
24// Higher versions will be used before lower, 0x10-0xffffffef is the version\r
25// range for IHV (Indie Hardware Vendors)\r
26//\r
27#define PVSCSI_BINDING_VERSION 0x10\r
28\r
7efce2e5
LA
29//\r
30// Ext SCSI Pass Thru utilities\r
31//\r
32\r
5269c26e
LA
33/**\r
34 Writes a 32-bit value into BAR0 using MMIO\r
35**/\r
36STATIC\r
37EFI_STATUS\r
38PvScsiMmioWrite32 (\r
39 IN CONST PVSCSI_DEV *Dev,\r
40 IN UINT64 Offset,\r
41 IN UINT32 Value\r
42 )\r
43{\r
44 return Dev->PciIo->Mem.Write (\r
45 Dev->PciIo,\r
46 EfiPciIoWidthUint32,\r
47 PCI_BAR_IDX0,\r
48 Offset,\r
49 1, // Count\r
50 &Value\r
51 );\r
52}\r
53\r
54/**\r
55 Writes multiple words of data into BAR0 using MMIO\r
56**/\r
57STATIC\r
58EFI_STATUS\r
59PvScsiMmioWrite32Multiple (\r
60 IN CONST PVSCSI_DEV *Dev,\r
61 IN UINT64 Offset,\r
62 IN UINTN Count,\r
63 IN UINT32 *Words\r
64 )\r
65{\r
66 return Dev->PciIo->Mem.Write (\r
67 Dev->PciIo,\r
68 EfiPciIoWidthFifoUint32,\r
69 PCI_BAR_IDX0,\r
70 Offset,\r
71 Count,\r
72 Words\r
73 );\r
74}\r
75\r
76/**\r
77 Send a PVSCSI command to device.\r
78\r
79 @param[in] Dev The pvscsi host device.\r
80 @param[in] Cmd The command to send to device.\r
81 @param[in] OPTIONAL DescWords An optional command descriptor (If command\r
82 have a descriptor). The descriptor is\r
83 provided as an array of UINT32 words and\r
84 is must be 32-bit aligned.\r
85 @param[in] DescWordsCount The number of words in command descriptor.\r
86 Caller must specify here 0 if DescWords\r
87 is not supplied (It is optional). In that\r
88 case, DescWords is ignored.\r
89\r
90 @return Status codes returned by Dev->PciIo->Mem.Write().\r
91\r
92**/\r
93STATIC\r
94EFI_STATUS\r
95PvScsiWriteCmdDesc (\r
96 IN CONST PVSCSI_DEV *Dev,\r
97 IN UINT32 Cmd,\r
98 IN UINT32 *DescWords OPTIONAL,\r
99 IN UINTN DescWordsCount\r
100 )\r
101{\r
102 EFI_STATUS Status;\r
103\r
104 if (DescWordsCount > PVSCSI_MAX_CMD_DATA_WORDS) {\r
105 return EFI_INVALID_PARAMETER;\r
106 }\r
107\r
108 Status = PvScsiMmioWrite32 (Dev, PvScsiRegOffsetCommand, Cmd);\r
109 if (EFI_ERROR (Status)) {\r
110 return Status;\r
111 }\r
112\r
113 if (DescWordsCount > 0) {\r
114 return PvScsiMmioWrite32Multiple (\r
115 Dev,\r
116 PvScsiRegOffsetCommandData,\r
117 DescWordsCount,\r
118 DescWords\r
119 );\r
120 }\r
121\r
122 return EFI_SUCCESS;\r
123}\r
124\r
125STATIC\r
126EFI_STATUS\r
127PvScsiResetAdapter (\r
128 IN CONST PVSCSI_DEV *Dev\r
129 )\r
130{\r
131 return PvScsiWriteCmdDesc (Dev, PvScsiCmdAdapterReset, NULL, 0);\r
132}\r
133\r
7efce2e5
LA
134/**\r
135 Check if Target argument to EXT_SCSI_PASS_THRU.GetNextTarget() and\r
136 EXT_SCSI_PASS_THRU.GetNextTargetLun() is initialized\r
137**/\r
138STATIC\r
139BOOLEAN\r
140IsTargetInitialized (\r
141 IN UINT8 *Target\r
142 )\r
143{\r
144 UINTN Idx;\r
145\r
146 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {\r
147 if (Target[Idx] != 0xFF) {\r
148 return TRUE;\r
149 }\r
150 }\r
151 return FALSE;\r
152}\r
153\r
e497432c
LA
154//\r
155// Ext SCSI Pass Thru\r
156//\r
157\r
158STATIC\r
159EFI_STATUS\r
160EFIAPI\r
161PvScsiPassThru (\r
162 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
163 IN UINT8 *Target,\r
164 IN UINT64 Lun,\r
165 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
166 IN EFI_EVENT Event OPTIONAL\r
167 )\r
168{\r
169 return EFI_UNSUPPORTED;\r
170}\r
171\r
172STATIC\r
173EFI_STATUS\r
174EFIAPI\r
175PvScsiGetNextTargetLun (\r
176 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
177 IN OUT UINT8 **Target,\r
178 IN OUT UINT64 *Lun\r
179 )\r
180{\r
7efce2e5
LA
181 UINT8 *TargetPtr;\r
182 UINT8 LastTarget;\r
183 PVSCSI_DEV *Dev;\r
184\r
185 if (Target == NULL) {\r
186 return EFI_INVALID_PARAMETER;\r
187 }\r
188\r
189 //\r
190 // The Target input parameter is unnecessarily a pointer-to-pointer\r
191 //\r
192 TargetPtr = *Target;\r
193\r
194 //\r
195 // If target not initialized, return first target & LUN\r
196 //\r
197 if (!IsTargetInitialized (TargetPtr)) {\r
198 ZeroMem (TargetPtr, TARGET_MAX_BYTES);\r
199 *Lun = 0;\r
200 return EFI_SUCCESS;\r
201 }\r
202\r
203 //\r
204 // We only use first byte of target identifer\r
205 //\r
206 LastTarget = *TargetPtr;\r
207\r
208 //\r
209 // Increment (target, LUN) pair if valid on input\r
210 //\r
211 Dev = PVSCSI_FROM_PASS_THRU (This);\r
212 if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {\r
213 return EFI_INVALID_PARAMETER;\r
214 }\r
215\r
216 if (*Lun < Dev->MaxLun) {\r
217 ++*Lun;\r
218 return EFI_SUCCESS;\r
219 }\r
220\r
221 if (LastTarget < Dev->MaxTarget) {\r
222 *Lun = 0;\r
223 ++LastTarget;\r
224 *TargetPtr = LastTarget;\r
225 return EFI_SUCCESS;\r
226 }\r
227\r
228 return EFI_NOT_FOUND;\r
e497432c
LA
229}\r
230\r
231STATIC\r
232EFI_STATUS\r
233EFIAPI\r
234PvScsiBuildDevicePath (\r
235 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
236 IN UINT8 *Target,\r
237 IN UINT64 Lun,\r
238 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
239 )\r
240{\r
9c2d8281
LA
241 UINT8 TargetValue;\r
242 PVSCSI_DEV *Dev;\r
243 SCSI_DEVICE_PATH *ScsiDevicePath;\r
244\r
245 if (DevicePath == NULL) {\r
246 return EFI_INVALID_PARAMETER;\r
247 }\r
248\r
249 //\r
250 // We only use first byte of target identifer\r
251 //\r
252 TargetValue = *Target;\r
253\r
254 Dev = PVSCSI_FROM_PASS_THRU (This);\r
255 if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun) {\r
256 return EFI_NOT_FOUND;\r
257 }\r
258\r
259 ScsiDevicePath = AllocatePool (sizeof (*ScsiDevicePath));\r
260 if (ScsiDevicePath == NULL) {\r
261 return EFI_OUT_OF_RESOURCES;\r
262 }\r
263\r
264 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;\r
265 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;\r
266 ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);\r
267 ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);\r
268 ScsiDevicePath->Pun = TargetValue;\r
269 ScsiDevicePath->Lun = (UINT16)Lun;\r
270\r
271 *DevicePath = &ScsiDevicePath->Header;\r
272 return EFI_SUCCESS;\r
e497432c
LA
273}\r
274\r
275STATIC\r
276EFI_STATUS\r
277EFIAPI\r
278PvScsiGetTargetLun (\r
279 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
280 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
281 OUT UINT8 **Target,\r
282 OUT UINT64 *Lun\r
283 )\r
284{\r
9c2d8281
LA
285 SCSI_DEVICE_PATH *ScsiDevicePath;\r
286 PVSCSI_DEV *Dev;\r
287\r
288 if (DevicePath == NULL || Target == NULL || *Target == NULL || Lun == NULL) {\r
289 return EFI_INVALID_PARAMETER;\r
290 }\r
291\r
292 if (DevicePath->Type != MESSAGING_DEVICE_PATH ||\r
293 DevicePath->SubType != MSG_SCSI_DP) {\r
294 return EFI_UNSUPPORTED;\r
295 }\r
296\r
297 ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;\r
298 Dev = PVSCSI_FROM_PASS_THRU (This);\r
299 if (ScsiDevicePath->Pun > Dev->MaxTarget ||\r
300 ScsiDevicePath->Lun > Dev->MaxLun) {\r
301 return EFI_NOT_FOUND;\r
302 }\r
303\r
304 //\r
305 // We only use first byte of target identifer\r
306 //\r
307 **Target = (UINT8)ScsiDevicePath->Pun;\r
308 ZeroMem (*Target + 1, TARGET_MAX_BYTES - 1);\r
309 *Lun = ScsiDevicePath->Lun;\r
310\r
311 return EFI_SUCCESS;\r
e497432c
LA
312}\r
313\r
314STATIC\r
315EFI_STATUS\r
316EFIAPI\r
317PvScsiResetChannel (\r
318 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
319 )\r
320{\r
321 return EFI_UNSUPPORTED;\r
322}\r
323\r
324STATIC\r
325EFI_STATUS\r
326EFIAPI\r
327PvScsiResetTargetLun (\r
328 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
329 IN UINT8 *Target,\r
330 IN UINT64 Lun\r
331 )\r
332{\r
333 return EFI_UNSUPPORTED;\r
334}\r
335\r
336STATIC\r
337EFI_STATUS\r
338EFIAPI\r
339PvScsiGetNextTarget (\r
340 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
341 IN OUT UINT8 **Target\r
342 )\r
343{\r
7efce2e5
LA
344 UINT8 *TargetPtr;\r
345 UINT8 LastTarget;\r
346 PVSCSI_DEV *Dev;\r
347\r
348 if (Target == NULL) {\r
349 return EFI_INVALID_PARAMETER;\r
350 }\r
351\r
352 //\r
353 // The Target input parameter is unnecessarily a pointer-to-pointer\r
354 //\r
355 TargetPtr = *Target;\r
356\r
357 //\r
358 // If target not initialized, return first target\r
359 //\r
360 if (!IsTargetInitialized (TargetPtr)) {\r
361 ZeroMem (TargetPtr, TARGET_MAX_BYTES);\r
362 return EFI_SUCCESS;\r
363 }\r
364\r
365 //\r
366 // We only use first byte of target identifer\r
367 //\r
368 LastTarget = *TargetPtr;\r
369\r
370 //\r
371 // Increment target if valid on input\r
372 //\r
373 Dev = PVSCSI_FROM_PASS_THRU (This);\r
374 if (LastTarget > Dev->MaxTarget) {\r
375 return EFI_INVALID_PARAMETER;\r
376 }\r
377\r
378 if (LastTarget < Dev->MaxTarget) {\r
379 ++LastTarget;\r
380 *TargetPtr = LastTarget;\r
381 return EFI_SUCCESS;\r
382 }\r
383\r
384 return EFI_NOT_FOUND;\r
e497432c
LA
385}\r
386\r
45098e8a
LA
387STATIC\r
388EFI_STATUS\r
389PvScsiSetPciAttributes (\r
390 IN OUT PVSCSI_DEV *Dev\r
391 )\r
392{\r
393 EFI_STATUS Status;\r
394\r
395 //\r
396 // Backup original PCI Attributes\r
397 //\r
398 Status = Dev->PciIo->Attributes (\r
399 Dev->PciIo,\r
400 EfiPciIoAttributeOperationGet,\r
401 0,\r
402 &Dev->OriginalPciAttributes\r
403 );\r
404 if (EFI_ERROR (Status)) {\r
405 return Status;\r
406 }\r
407\r
408 //\r
6672b3cf 409 // Enable MMIO-Space & Bus-Mastering\r
45098e8a 410 //\r
6672b3cf
LA
411 Status = Dev->PciIo->Attributes (\r
412 Dev->PciIo,\r
413 EfiPciIoAttributeOperationEnable,\r
414 (EFI_PCI_IO_ATTRIBUTE_MEMORY |\r
415 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
416 NULL\r
417 );\r
418 if (EFI_ERROR (Status)) {\r
419 return Status;\r
420 }\r
45098e8a
LA
421\r
422 return EFI_SUCCESS;\r
423}\r
424\r
425STATIC\r
426VOID\r
427PvScsiRestorePciAttributes (\r
428 IN PVSCSI_DEV *Dev\r
429 )\r
430{\r
431 Dev->PciIo->Attributes (\r
432 Dev->PciIo,\r
433 EfiPciIoAttributeOperationSet,\r
434 Dev->OriginalPciAttributes,\r
435 NULL\r
436 );\r
437}\r
438\r
e497432c
LA
439STATIC\r
440EFI_STATUS\r
441PvScsiInit (\r
442 IN OUT PVSCSI_DEV *Dev\r
443 )\r
444{\r
45098e8a
LA
445 EFI_STATUS Status;\r
446\r
7efce2e5
LA
447 //\r
448 // Init configuration\r
449 //\r
450 Dev->MaxTarget = PcdGet8 (PcdPvScsiMaxTargetLimit);\r
451 Dev->MaxLun = PcdGet8 (PcdPvScsiMaxLunLimit);\r
452\r
45098e8a
LA
453 //\r
454 // Set PCI Attributes\r
455 //\r
456 Status = PvScsiSetPciAttributes (Dev);\r
457 if (EFI_ERROR (Status)) {\r
458 return Status;\r
459 }\r
460\r
5269c26e
LA
461 //\r
462 // Reset adapter\r
463 //\r
464 Status = PvScsiResetAdapter (Dev);\r
465 if (EFI_ERROR (Status)) {\r
466 goto RestorePciAttributes;\r
467 }\r
468\r
e497432c
LA
469 //\r
470 // Populate the exported interface's attributes\r
471 //\r
472 Dev->PassThru.Mode = &Dev->PassThruMode;\r
473 Dev->PassThru.PassThru = &PvScsiPassThru;\r
474 Dev->PassThru.GetNextTargetLun = &PvScsiGetNextTargetLun;\r
475 Dev->PassThru.BuildDevicePath = &PvScsiBuildDevicePath;\r
476 Dev->PassThru.GetTargetLun = &PvScsiGetTargetLun;\r
477 Dev->PassThru.ResetChannel = &PvScsiResetChannel;\r
478 Dev->PassThru.ResetTargetLun = &PvScsiResetTargetLun;\r
479 Dev->PassThru.GetNextTarget = &PvScsiGetNextTarget;\r
480\r
481 //\r
482 // AdapterId is a target for which no handle will be created during bus scan.\r
483 // Prevent any conflict with real devices.\r
484 //\r
485 Dev->PassThruMode.AdapterId = MAX_UINT32;\r
486\r
487 //\r
488 // Set both physical and logical attributes for non-RAID SCSI channel\r
489 //\r
490 Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
491 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
492\r
493 //\r
494 // No restriction on transfer buffer alignment\r
495 //\r
496 Dev->PassThruMode.IoAlign = 0;\r
497\r
498 return EFI_SUCCESS;\r
5269c26e
LA
499\r
500RestorePciAttributes:\r
501 PvScsiRestorePciAttributes (Dev);\r
502\r
503 return Status;\r
e497432c
LA
504}\r
505\r
506STATIC\r
507VOID\r
508PvScsiUninit (\r
509 IN OUT PVSCSI_DEV *Dev\r
510 )\r
511{\r
45098e8a 512 PvScsiRestorePciAttributes (Dev);\r
e497432c
LA
513}\r
514\r
ed08c571
LA
515//\r
516// Driver Binding\r
517//\r
518\r
519STATIC\r
520EFI_STATUS\r
521EFIAPI\r
522PvScsiDriverBindingSupported (\r
523 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
524 IN EFI_HANDLE ControllerHandle,\r
525 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
526 )\r
527{\r
a9f9d5cf
LA
528 EFI_STATUS Status;\r
529 EFI_PCI_IO_PROTOCOL *PciIo;\r
530 PCI_TYPE00 Pci;\r
531\r
532 Status = gBS->OpenProtocol (\r
533 ControllerHandle,\r
534 &gEfiPciIoProtocolGuid,\r
535 (VOID **)&PciIo,\r
536 This->DriverBindingHandle,\r
537 ControllerHandle,\r
538 EFI_OPEN_PROTOCOL_BY_DRIVER\r
539 );\r
540 if (EFI_ERROR (Status)) {\r
541 return Status;\r
542 }\r
543\r
544 Status = PciIo->Pci.Read (\r
545 PciIo,\r
546 EfiPciIoWidthUint32,\r
547 0,\r
548 sizeof (Pci) / sizeof (UINT32),\r
549 &Pci\r
550 );\r
551 if (EFI_ERROR (Status)) {\r
552 goto Done;\r
553 }\r
554\r
555 if ((Pci.Hdr.VendorId != PCI_VENDOR_ID_VMWARE) ||\r
556 (Pci.Hdr.DeviceId != PCI_DEVICE_ID_VMWARE_PVSCSI)) {\r
557 Status = EFI_UNSUPPORTED;\r
558 goto Done;\r
559 }\r
560\r
561 Status = EFI_SUCCESS;\r
562\r
563Done:\r
564 gBS->CloseProtocol (\r
565 ControllerHandle,\r
566 &gEfiPciIoProtocolGuid,\r
567 This->DriverBindingHandle,\r
568 ControllerHandle\r
569 );\r
570\r
571 return Status;\r
ed08c571
LA
572}\r
573\r
574STATIC\r
575EFI_STATUS\r
576EFIAPI\r
577PvScsiDriverBindingStart (\r
578 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
579 IN EFI_HANDLE ControllerHandle,\r
580 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
581 )\r
582{\r
e497432c
LA
583 PVSCSI_DEV *Dev;\r
584 EFI_STATUS Status;\r
585\r
586 Dev = (PVSCSI_DEV *) AllocateZeroPool (sizeof (*Dev));\r
587 if (Dev == NULL) {\r
588 return EFI_OUT_OF_RESOURCES;\r
589 }\r
590\r
c08eaaaf
LA
591 Status = gBS->OpenProtocol (\r
592 ControllerHandle,\r
593 &gEfiPciIoProtocolGuid,\r
594 (VOID **)&Dev->PciIo,\r
595 This->DriverBindingHandle,\r
596 ControllerHandle,\r
597 EFI_OPEN_PROTOCOL_BY_DRIVER\r
598 );\r
e497432c
LA
599 if (EFI_ERROR (Status)) {\r
600 goto FreePvScsi;\r
601 }\r
602\r
c08eaaaf
LA
603 Status = PvScsiInit (Dev);\r
604 if (EFI_ERROR (Status)) {\r
605 goto ClosePciIo;\r
606 }\r
607\r
e497432c
LA
608 //\r
609 // Setup complete, attempt to export the driver instance's PassThru interface\r
610 //\r
611 Dev->Signature = PVSCSI_SIG;\r
612 Status = gBS->InstallProtocolInterface (\r
613 &ControllerHandle,\r
614 &gEfiExtScsiPassThruProtocolGuid,\r
615 EFI_NATIVE_INTERFACE,\r
616 &Dev->PassThru\r
617 );\r
618 if (EFI_ERROR (Status)) {\r
619 goto UninitDev;\r
620 }\r
621\r
622 return EFI_SUCCESS;\r
623\r
624UninitDev:\r
625 PvScsiUninit (Dev);\r
626\r
c08eaaaf
LA
627ClosePciIo:\r
628 gBS->CloseProtocol (\r
629 ControllerHandle,\r
630 &gEfiPciIoProtocolGuid,\r
631 This->DriverBindingHandle,\r
632 ControllerHandle\r
633 );\r
634\r
e497432c
LA
635FreePvScsi:\r
636 FreePool (Dev);\r
637\r
638 return Status;\r
ed08c571
LA
639}\r
640\r
641STATIC\r
642EFI_STATUS\r
643EFIAPI\r
644PvScsiDriverBindingStop (\r
645 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
646 IN EFI_HANDLE ControllerHandle,\r
647 IN UINTN NumberOfChildren,\r
648 IN EFI_HANDLE *ChildHandleBuffer\r
649 )\r
650{\r
e497432c
LA
651 EFI_STATUS Status;\r
652 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
653 PVSCSI_DEV *Dev;\r
654\r
655 Status = gBS->OpenProtocol (\r
656 ControllerHandle,\r
657 &gEfiExtScsiPassThruProtocolGuid,\r
658 (VOID **)&PassThru,\r
659 This->DriverBindingHandle,\r
660 ControllerHandle,\r
661 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only\r
662 );\r
663 if (EFI_ERROR (Status)) {\r
664 return Status;\r
665 }\r
666\r
667 Dev = PVSCSI_FROM_PASS_THRU (PassThru);\r
668\r
669 Status = gBS->UninstallProtocolInterface (\r
670 ControllerHandle,\r
671 &gEfiExtScsiPassThruProtocolGuid,\r
672 &Dev->PassThru\r
673 );\r
674 if (EFI_ERROR (Status)) {\r
675 return Status;\r
676 }\r
677\r
678 PvScsiUninit (Dev);\r
679\r
c08eaaaf
LA
680 gBS->CloseProtocol (\r
681 ControllerHandle,\r
682 &gEfiPciIoProtocolGuid,\r
683 This->DriverBindingHandle,\r
684 ControllerHandle\r
685 );\r
686\r
e497432c
LA
687 FreePool (Dev);\r
688\r
689 return EFI_SUCCESS;\r
ed08c571
LA
690}\r
691\r
692STATIC EFI_DRIVER_BINDING_PROTOCOL mPvScsiDriverBinding = {\r
693 &PvScsiDriverBindingSupported,\r
694 &PvScsiDriverBindingStart,\r
695 &PvScsiDriverBindingStop,\r
696 PVSCSI_BINDING_VERSION,\r
697 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2()\r
698 NULL // DriverBindingHandle, filled as well\r
699};\r
700\r
419b30d6
LA
701//\r
702// Component Name\r
703//\r
704\r
705STATIC EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
706 { "eng;en", L"PVSCSI Host Driver" },\r
707 { NULL, NULL }\r
708};\r
709\r
710STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName;\r
711\r
712STATIC\r
713EFI_STATUS\r
714EFIAPI\r
715PvScsiGetDriverName (\r
716 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
717 IN CHAR8 *Language,\r
718 OUT CHAR16 **DriverName\r
719 )\r
720{\r
721 return LookupUnicodeString2 (\r
722 Language,\r
723 This->SupportedLanguages,\r
724 mDriverNameTable,\r
725 DriverName,\r
726 (BOOLEAN)(This == &mComponentName) // Iso639Language\r
727 );\r
728}\r
729\r
730STATIC\r
731EFI_STATUS\r
732EFIAPI\r
733PvScsiGetDeviceName (\r
734 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
735 IN EFI_HANDLE DeviceHandle,\r
736 IN EFI_HANDLE ChildHandle,\r
737 IN CHAR8 *Language,\r
738 OUT CHAR16 **ControllerName\r
739 )\r
740{\r
741 return EFI_UNSUPPORTED;\r
742}\r
743\r
744STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName = {\r
745 &PvScsiGetDriverName,\r
746 &PvScsiGetDeviceName,\r
747 "eng" // SupportedLanguages, ISO 639-2 language codes\r
748};\r
749\r
750STATIC EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {\r
751 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &PvScsiGetDriverName,\r
752 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &PvScsiGetDeviceName,\r
753 "en" // SupportedLanguages, RFC 4646 language codes\r
754};\r
755\r
478c07d4
LA
756//\r
757// Entry Point\r
758//\r
759\r
760EFI_STATUS\r
761EFIAPI\r
762PvScsiEntryPoint (\r
763 IN EFI_HANDLE ImageHandle,\r
764 IN EFI_SYSTEM_TABLE *SystemTable\r
765 )\r
766{\r
ed08c571
LA
767 return EfiLibInstallDriverBindingComponentName2 (\r
768 ImageHandle,\r
769 SystemTable,\r
770 &mPvScsiDriverBinding,\r
771 ImageHandle,\r
419b30d6
LA
772 &mComponentName,\r
773 &mComponentName2\r
ed08c571 774 );\r
478c07d4 775}\r