1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570 |
- /** @file
- This driver produces Extended SCSI Pass Thru Protocol instances for
- pvscsi devices.
- Copyright (C) 2020, Oracle and/or its affiliates.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <IndustryStandard/Pci.h>
- #include <IndustryStandard/PvScsi.h>
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiLib.h>
- #include <Protocol/PciIo.h>
- #include <Protocol/PciRootBridgeIo.h>
- #include <Uefi/UefiSpec.h>
- #include "PvScsi.h"
- //
- // Higher versions will be used before lower, 0x10-0xffffffef is the version
- // range for IHV (Indie Hardware Vendors)
- //
- #define PVSCSI_BINDING_VERSION 0x10
- //
- // Ext SCSI Pass Thru utilities
- //
- /**
- Reads a 32-bit value into BAR0 using MMIO
- **/
- STATIC
- EFI_STATUS
- PvScsiMmioRead32 (
- IN CONST PVSCSI_DEV *Dev,
- IN UINT64 Offset,
- OUT UINT32 *Value
- )
- {
- return Dev->PciIo->Mem.Read (
- Dev->PciIo,
- EfiPciIoWidthUint32,
- PCI_BAR_IDX0,
- Offset,
- 1, // Count
- Value
- );
- }
- /**
- Writes a 32-bit value into BAR0 using MMIO
- **/
- STATIC
- EFI_STATUS
- PvScsiMmioWrite32 (
- IN CONST PVSCSI_DEV *Dev,
- IN UINT64 Offset,
- IN UINT32 Value
- )
- {
- return Dev->PciIo->Mem.Write (
- Dev->PciIo,
- EfiPciIoWidthUint32,
- PCI_BAR_IDX0,
- Offset,
- 1, // Count
- &Value
- );
- }
- /**
- Writes multiple words of data into BAR0 using MMIO
- **/
- STATIC
- EFI_STATUS
- PvScsiMmioWrite32Multiple (
- IN CONST PVSCSI_DEV *Dev,
- IN UINT64 Offset,
- IN UINTN Count,
- IN UINT32 *Words
- )
- {
- return Dev->PciIo->Mem.Write (
- Dev->PciIo,
- EfiPciIoWidthFifoUint32,
- PCI_BAR_IDX0,
- Offset,
- Count,
- Words
- );
- }
- /**
- Send a PVSCSI command to device.
- @param[in] Dev The pvscsi host device.
- @param[in] Cmd The command to send to device.
- @param[in] OPTIONAL DescWords An optional command descriptor (If command
- have a descriptor). The descriptor is
- provided as an array of UINT32 words and
- is must be 32-bit aligned.
- @param[in] DescWordsCount The number of words in command descriptor.
- Caller must specify here 0 if DescWords
- is not supplied (It is optional). In that
- case, DescWords is ignored.
- @return Status codes returned by Dev->PciIo->Mem.Write().
- **/
- STATIC
- EFI_STATUS
- PvScsiWriteCmdDesc (
- IN CONST PVSCSI_DEV *Dev,
- IN UINT32 Cmd,
- IN UINT32 *DescWords OPTIONAL,
- IN UINTN DescWordsCount
- )
- {
- EFI_STATUS Status;
- if (DescWordsCount > PVSCSI_MAX_CMD_DATA_WORDS) {
- return EFI_INVALID_PARAMETER;
- }
- Status = PvScsiMmioWrite32 (Dev, PvScsiRegOffsetCommand, Cmd);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (DescWordsCount > 0) {
- return PvScsiMmioWrite32Multiple (
- Dev,
- PvScsiRegOffsetCommandData,
- DescWordsCount,
- DescWords
- );
- }
- return EFI_SUCCESS;
- }
- STATIC
- EFI_STATUS
- PvScsiResetAdapter (
- IN CONST PVSCSI_DEV *Dev
- )
- {
- return PvScsiWriteCmdDesc (Dev, PvScsiCmdAdapterReset, NULL, 0);
- }
- /**
- Returns if PVSCSI request ring is full
- **/
- STATIC
- BOOLEAN
- PvScsiIsReqRingFull (
- IN CONST PVSCSI_DEV *Dev
- )
- {
- PVSCSI_RINGS_STATE *RingsState;
- UINT32 ReqNumEntries;
- RingsState = Dev->RingDesc.RingState;
- ReqNumEntries = 1U << RingsState->ReqNumEntriesLog2;
- return (RingsState->ReqProdIdx - RingsState->CmpConsIdx) >= ReqNumEntries;
- }
- /**
- Returns pointer to current request descriptor to produce
- **/
- STATIC
- PVSCSI_RING_REQ_DESC *
- PvScsiGetCurrentRequest (
- IN CONST PVSCSI_DEV *Dev
- )
- {
- PVSCSI_RINGS_STATE *RingState;
- UINT32 ReqNumEntries;
- RingState = Dev->RingDesc.RingState;
- ReqNumEntries = 1U << RingState->ReqNumEntriesLog2;
- return Dev->RingDesc.RingReqs +
- (RingState->ReqProdIdx & (ReqNumEntries - 1));
- }
- /**
- Returns pointer to current completion descriptor to consume
- **/
- STATIC
- PVSCSI_RING_CMP_DESC *
- PvScsiGetCurrentResponse (
- IN CONST PVSCSI_DEV *Dev
- )
- {
- PVSCSI_RINGS_STATE *RingState;
- UINT32 CmpNumEntries;
- RingState = Dev->RingDesc.RingState;
- CmpNumEntries = 1U << RingState->CmpNumEntriesLog2;
- return Dev->RingDesc.RingCmps +
- (RingState->CmpConsIdx & (CmpNumEntries - 1));
- }
- /**
- Wait for device to signal completion of submitted requests
- **/
- STATIC
- EFI_STATUS
- PvScsiWaitForRequestCompletion (
- IN CONST PVSCSI_DEV *Dev
- )
- {
- EFI_STATUS Status;
- UINT32 IntrStatus;
- //
- // Note: We don't yet support Timeout according to
- // EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.Timeout.
- //
- // This is consistent with some other Scsi PassThru drivers
- // such as VirtioScsi.
- //
- for ( ; ;) {
- Status = PvScsiMmioRead32 (Dev, PvScsiRegOffsetIntrStatus, &IntrStatus);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // PVSCSI_INTR_CMPL_MASK is set if device completed submitted requests
- //
- if ((IntrStatus & PVSCSI_INTR_CMPL_MASK) != 0) {
- break;
- }
- gBS->Stall (Dev->WaitForCmpStallInUsecs);
- }
- //
- // Acknowledge PVSCSI_INTR_CMPL_MASK in device interrupt-status register
- //
- return PvScsiMmioWrite32 (
- Dev,
- PvScsiRegOffsetIntrStatus,
- PVSCSI_INTR_CMPL_MASK
- );
- }
- /**
- Create a fake host adapter error
- **/
- STATIC
- EFI_STATUS
- ReportHostAdapterError (
- OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
- )
- {
- Packet->InTransferLength = 0;
- Packet->OutTransferLength = 0;
- Packet->SenseDataLength = 0;
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
- Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
- return EFI_DEVICE_ERROR;
- }
- /**
- Create a fake host adapter overrun error
- **/
- STATIC
- EFI_STATUS
- ReportHostAdapterOverrunError (
- OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
- )
- {
- Packet->SenseDataLength = 0;
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
- Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
- return EFI_BAD_BUFFER_SIZE;
- }
- /**
- Populate a PVSCSI request descriptor from the Extended SCSI Pass Thru
- Protocol packet.
- **/
- STATIC
- EFI_STATUS
- PopulateRequest (
- IN CONST PVSCSI_DEV *Dev,
- IN UINT8 *Target,
- IN UINT64 Lun,
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
- OUT PVSCSI_RING_REQ_DESC *Request
- )
- {
- UINT8 TargetValue;
- //
- // We only use first byte of target identifer
- //
- TargetValue = *Target;
- //
- // Check for unsupported requests
- //
- if (
- //
- // Bidirectional transfer was requested
- //
- ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0)) ||
- (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
- //
- // Command Descriptor Block bigger than this constant should be considered
- // out-of-band. We currently don't support these CDBs.
- //
- (Packet->CdbLength > PVSCSI_CDB_MAX_SIZE)
- )
- {
- //
- // This error code doesn't require updates to the Packet output fields
- //
- return EFI_UNSUPPORTED;
- }
- //
- // Check for invalid parameters
- //
- if (
- //
- // Addressed invalid device
- //
- (TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun) ||
- //
- // Invalid direction (there doesn't seem to be a macro for the "no data
- // transferred" "direction", eg. for TEST UNIT READY)
- //
- (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
- //
- // Trying to receive, but destination pointer is NULL, or contradicting
- // transfer direction
- //
- ((Packet->InTransferLength > 0) &&
- ((Packet->InDataBuffer == NULL) ||
- (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)
- )
- ) ||
- //
- // Trying to send, but source pointer is NULL, or contradicting
- // transfer direction
- //
- ((Packet->OutTransferLength > 0) &&
- ((Packet->OutDataBuffer == NULL) ||
- (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)
- )
- )
- )
- {
- //
- // This error code doesn't require updates to the Packet output fields
- //
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check for input/output buffer too large for DMA communication buffer
- //
- if (Packet->InTransferLength > sizeof (Dev->DmaBuf->Data)) {
- Packet->InTransferLength = sizeof (Dev->DmaBuf->Data);
- return ReportHostAdapterOverrunError (Packet);
- }
- if (Packet->OutTransferLength > sizeof (Dev->DmaBuf->Data)) {
- Packet->OutTransferLength = sizeof (Dev->DmaBuf->Data);
- return ReportHostAdapterOverrunError (Packet);
- }
- //
- // Encode PVSCSI request
- //
- ZeroMem (Request, sizeof (*Request));
- Request->Bus = 0;
- Request->Target = TargetValue;
- //
- // This cast is safe as PVSCSI_DEV.MaxLun is defined as UINT8
- //
- Request->Lun[1] = (UINT8)Lun;
- Request->SenseLen = Packet->SenseDataLength;
- //
- // DMA communication buffer SenseData overflow is not possible
- // due to Packet->SenseDataLength defined as UINT8
- //
- Request->SenseAddr = PVSCSI_DMA_BUF_DEV_ADDR (Dev, SenseData);
- Request->CdbLen = Packet->CdbLength;
- CopyMem (Request->Cdb, Packet->Cdb, Packet->CdbLength);
- Request->VcpuHint = 0;
- Request->Tag = PVSCSI_SIMPLE_QUEUE_TAG;
- if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
- Request->Flags = PVSCSI_FLAG_CMD_DIR_TOHOST;
- Request->DataLen = Packet->InTransferLength;
- } else {
- Request->Flags = PVSCSI_FLAG_CMD_DIR_TODEVICE;
- Request->DataLen = Packet->OutTransferLength;
- CopyMem (
- Dev->DmaBuf->Data,
- Packet->OutDataBuffer,
- Packet->OutTransferLength
- );
- }
- Request->DataAddr = PVSCSI_DMA_BUF_DEV_ADDR (Dev, Data);
- return EFI_SUCCESS;
- }
- /**
- Handle the PVSCSI device response:
- - Copy returned data from DMA communication buffer.
- - Update fields in Extended SCSI Pass Thru Protocol packet as required.
- - Translate response code to EFI status code and host adapter status.
- **/
- STATIC
- EFI_STATUS
- HandleResponse (
- IN PVSCSI_DEV *Dev,
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
- IN CONST PVSCSI_RING_CMP_DESC *Response
- )
- {
- //
- // Fix SenseDataLength to amount of data returned
- //
- if (Packet->SenseDataLength > Response->SenseLen) {
- Packet->SenseDataLength = (UINT8)Response->SenseLen;
- }
- //
- // Copy sense data from DMA communication buffer
- //
- CopyMem (
- Packet->SenseData,
- Dev->DmaBuf->SenseData,
- Packet->SenseDataLength
- );
- //
- // Copy device output from DMA communication buffer
- //
- if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
- CopyMem (Packet->InDataBuffer, Dev->DmaBuf->Data, Packet->InTransferLength);
- }
- //
- // Report target status
- // (Strangely, PVSCSI interface defines Response->ScsiStatus as UINT16.
- // But it should de-facto always have a value that fits UINT8. To avoid
- // unexpected behavior, verify value is in UINT8 bounds before casting)
- //
- ASSERT (Response->ScsiStatus <= MAX_UINT8);
- Packet->TargetStatus = (UINT8)Response->ScsiStatus;
- //
- // Host adapter status and function return value depend on
- // device response's host status
- //
- switch (Response->HostStatus) {
- case PvScsiBtStatSuccess:
- case PvScsiBtStatLinkedCommandCompleted:
- case PvScsiBtStatLinkedCommandCompletedWithFlag:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
- return EFI_SUCCESS;
- case PvScsiBtStatDataUnderrun:
- //
- // Report transferred amount in underrun
- //
- if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
- Packet->InTransferLength = (UINT32)Response->DataLen;
- } else {
- Packet->OutTransferLength = (UINT32)Response->DataLen;
- }
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
- return EFI_SUCCESS;
- case PvScsiBtStatDatarun:
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
- return EFI_SUCCESS;
- case PvScsiBtStatSelTimeout:
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
- return EFI_TIMEOUT;
- case PvScsiBtStatBusFree:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE;
- break;
- case PvScsiBtStatInvPhase:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
- break;
- case PvScsiBtStatSensFailed:
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED;
- break;
- case PvScsiBtStatTagReject:
- case PvScsiBtStatBadMsg:
- Packet->HostAdapterStatus =
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT;
- break;
- case PvScsiBtStatBusReset:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;
- break;
- case PvScsiBtStatHaTimeout:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT;
- return EFI_TIMEOUT;
- case PvScsiBtStatScsiParity:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR;
- break;
- default:
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
- break;
- }
- return EFI_DEVICE_ERROR;
- }
- /**
- Check if Target argument to EXT_SCSI_PASS_THRU.GetNextTarget() and
- EXT_SCSI_PASS_THRU.GetNextTargetLun() is initialized
- **/
- STATIC
- BOOLEAN
- IsTargetInitialized (
- IN UINT8 *Target
- )
- {
- UINTN Idx;
- for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
- if (Target[Idx] != 0xFF) {
- return TRUE;
- }
- }
- return FALSE;
- }
- //
- // Ext SCSI Pass Thru
- //
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiPassThru (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun,
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
- IN EFI_EVENT Event OPTIONAL
- )
- {
- PVSCSI_DEV *Dev;
- EFI_STATUS Status;
- PVSCSI_RING_REQ_DESC *Request;
- PVSCSI_RING_CMP_DESC *Response;
- Dev = PVSCSI_FROM_PASS_THRU (This);
- if (PvScsiIsReqRingFull (Dev)) {
- return EFI_NOT_READY;
- }
- Request = PvScsiGetCurrentRequest (Dev);
- Status = PopulateRequest (Dev, Target, Lun, Packet, Request);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Writes to Request must be globally visible before making request
- // available to device
- //
- MemoryFence ();
- Dev->RingDesc.RingState->ReqProdIdx++;
- Status = PvScsiMmioWrite32 (Dev, PvScsiRegOffsetKickRwIo, 0);
- if (EFI_ERROR (Status)) {
- //
- // If kicking the host fails, we must fake a host adapter error.
- // EFI_NOT_READY would save us the effort, but it would also suggest that
- // the caller retry.
- //
- return ReportHostAdapterError (Packet);
- }
- Status = PvScsiWaitForRequestCompletion (Dev);
- if (EFI_ERROR (Status)) {
- //
- // If waiting for request completion fails, we must fake a host adapter
- // error. EFI_NOT_READY would save us the effort, but it would also suggest
- // that the caller retry.
- //
- return ReportHostAdapterError (Packet);
- }
- Response = PvScsiGetCurrentResponse (Dev);
- Status = HandleResponse (Dev, Packet, Response);
- //
- // Reads from response must complete before releasing completion entry
- // to device
- //
- MemoryFence ();
- Dev->RingDesc.RingState->CmpConsIdx++;
- return Status;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiGetNextTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN OUT UINT8 **Target,
- IN OUT UINT64 *Lun
- )
- {
- UINT8 *TargetPtr;
- UINT8 LastTarget;
- PVSCSI_DEV *Dev;
- if (Target == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // The Target input parameter is unnecessarily a pointer-to-pointer
- //
- TargetPtr = *Target;
- //
- // If target not initialized, return first target & LUN
- //
- if (!IsTargetInitialized (TargetPtr)) {
- ZeroMem (TargetPtr, TARGET_MAX_BYTES);
- *Lun = 0;
- return EFI_SUCCESS;
- }
- //
- // We only use first byte of target identifer
- //
- LastTarget = *TargetPtr;
- //
- // Increment (target, LUN) pair if valid on input
- //
- Dev = PVSCSI_FROM_PASS_THRU (This);
- if ((LastTarget > Dev->MaxTarget) || (*Lun > Dev->MaxLun)) {
- return EFI_INVALID_PARAMETER;
- }
- if (*Lun < Dev->MaxLun) {
- ++*Lun;
- return EFI_SUCCESS;
- }
- if (LastTarget < Dev->MaxTarget) {
- *Lun = 0;
- ++LastTarget;
- *TargetPtr = LastTarget;
- return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiBuildDevicePath (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
- )
- {
- UINT8 TargetValue;
- PVSCSI_DEV *Dev;
- SCSI_DEVICE_PATH *ScsiDevicePath;
- if (DevicePath == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // We only use first byte of target identifer
- //
- TargetValue = *Target;
- Dev = PVSCSI_FROM_PASS_THRU (This);
- if ((TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun)) {
- return EFI_NOT_FOUND;
- }
- ScsiDevicePath = AllocatePool (sizeof (*ScsiDevicePath));
- if (ScsiDevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
- ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
- ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);
- ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);
- ScsiDevicePath->Pun = TargetValue;
- ScsiDevicePath->Lun = (UINT16)Lun;
- *DevicePath = &ScsiDevicePath->Header;
- return EFI_SUCCESS;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiGetTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT UINT8 **Target,
- OUT UINT64 *Lun
- )
- {
- SCSI_DEVICE_PATH *ScsiDevicePath;
- PVSCSI_DEV *Dev;
- if ((DevicePath == NULL) || (Target == NULL) || (*Target == NULL) || (Lun == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
- (DevicePath->SubType != MSG_SCSI_DP))
- {
- return EFI_UNSUPPORTED;
- }
- ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
- Dev = PVSCSI_FROM_PASS_THRU (This);
- if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||
- (ScsiDevicePath->Lun > Dev->MaxLun))
- {
- return EFI_NOT_FOUND;
- }
- //
- // We only use first byte of target identifer
- //
- **Target = (UINT8)ScsiDevicePath->Pun;
- ZeroMem (*Target + 1, TARGET_MAX_BYTES - 1);
- *Lun = ScsiDevicePath->Lun;
- return EFI_SUCCESS;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiResetChannel (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
- )
- {
- return EFI_UNSUPPORTED;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiResetTargetLun (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN UINT8 *Target,
- IN UINT64 Lun
- )
- {
- return EFI_UNSUPPORTED;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiGetNextTarget (
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
- IN OUT UINT8 **Target
- )
- {
- UINT8 *TargetPtr;
- UINT8 LastTarget;
- PVSCSI_DEV *Dev;
- if (Target == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // The Target input parameter is unnecessarily a pointer-to-pointer
- //
- TargetPtr = *Target;
- //
- // If target not initialized, return first target
- //
- if (!IsTargetInitialized (TargetPtr)) {
- ZeroMem (TargetPtr, TARGET_MAX_BYTES);
- return EFI_SUCCESS;
- }
- //
- // We only use first byte of target identifer
- //
- LastTarget = *TargetPtr;
- //
- // Increment target if valid on input
- //
- Dev = PVSCSI_FROM_PASS_THRU (This);
- if (LastTarget > Dev->MaxTarget) {
- return EFI_INVALID_PARAMETER;
- }
- if (LastTarget < Dev->MaxTarget) {
- ++LastTarget;
- *TargetPtr = LastTarget;
- return EFI_SUCCESS;
- }
- return EFI_NOT_FOUND;
- }
- STATIC
- EFI_STATUS
- PvScsiSetPciAttributes (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- EFI_STATUS Status;
- //
- // Backup original PCI Attributes
- //
- Status = Dev->PciIo->Attributes (
- Dev->PciIo,
- EfiPciIoAttributeOperationGet,
- 0,
- &Dev->OriginalPciAttributes
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Enable MMIO-Space & Bus-Mastering
- //
- Status = Dev->PciIo->Attributes (
- Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- (EFI_PCI_IO_ATTRIBUTE_MEMORY |
- EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
- NULL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Signal device supports 64-bit DMA addresses
- //
- Status = Dev->PciIo->Attributes (
- Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
- NULL
- );
- if (EFI_ERROR (Status)) {
- //
- // Warn user that device will only be using 32-bit DMA addresses.
- //
- // Note that this does not prevent the device/driver from working
- // and therefore we only warn and continue as usual.
- //
- DEBUG ((
- DEBUG_WARN,
- "%a: failed to enable 64-bit DMA addresses\n",
- __FUNCTION__
- ));
- }
- return EFI_SUCCESS;
- }
- STATIC
- VOID
- PvScsiRestorePciAttributes (
- IN PVSCSI_DEV *Dev
- )
- {
- Dev->PciIo->Attributes (
- Dev->PciIo,
- EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes,
- NULL
- );
- }
- STATIC
- EFI_STATUS
- PvScsiAllocateSharedPages (
- IN PVSCSI_DEV *Dev,
- IN UINTN Pages,
- OUT VOID **HostAddress,
- OUT PVSCSI_DMA_DESC *DmaDesc
- )
- {
- EFI_STATUS Status;
- UINTN NumberOfBytes;
- Status = Dev->PciIo->AllocateBuffer (
- Dev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- Pages,
- HostAddress,
- EFI_PCI_ATTRIBUTE_MEMORY_CACHED
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
- Status = Dev->PciIo->Map (
- Dev->PciIo,
- EfiPciIoOperationBusMasterCommonBuffer,
- *HostAddress,
- &NumberOfBytes,
- &DmaDesc->DeviceAddress,
- &DmaDesc->Mapping
- );
- if (EFI_ERROR (Status)) {
- goto FreeBuffer;
- }
- if (NumberOfBytes != EFI_PAGES_TO_SIZE (Pages)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Unmap;
- }
- return EFI_SUCCESS;
- Unmap:
- Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);
- FreeBuffer:
- Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, *HostAddress);
- return Status;
- }
- STATIC
- VOID
- PvScsiFreeSharedPages (
- IN PVSCSI_DEV *Dev,
- IN UINTN Pages,
- IN VOID *HostAddress,
- IN PVSCSI_DMA_DESC *DmaDesc
- )
- {
- Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);
- Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, HostAddress);
- }
- STATIC
- EFI_STATUS
- PvScsiInitRings (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- EFI_STATUS Status;
- Status = PvScsiAllocateSharedPages (
- Dev,
- 1,
- (VOID **)&Dev->RingDesc.RingState,
- &Dev->RingDesc.RingStateDmaDesc
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- ZeroMem (Dev->RingDesc.RingState, EFI_PAGE_SIZE);
- Status = PvScsiAllocateSharedPages (
- Dev,
- 1,
- (VOID **)&Dev->RingDesc.RingReqs,
- &Dev->RingDesc.RingReqsDmaDesc
- );
- if (EFI_ERROR (Status)) {
- goto FreeRingState;
- }
- ZeroMem (Dev->RingDesc.RingReqs, EFI_PAGE_SIZE);
- Status = PvScsiAllocateSharedPages (
- Dev,
- 1,
- (VOID **)&Dev->RingDesc.RingCmps,
- &Dev->RingDesc.RingCmpsDmaDesc
- );
- if (EFI_ERROR (Status)) {
- goto FreeRingReqs;
- }
- ZeroMem (Dev->RingDesc.RingCmps, EFI_PAGE_SIZE);
- return EFI_SUCCESS;
- FreeRingReqs:
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingReqs,
- &Dev->RingDesc.RingReqsDmaDesc
- );
- FreeRingState:
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingState,
- &Dev->RingDesc.RingStateDmaDesc
- );
- return Status;
- }
- STATIC
- VOID
- PvScsiFreeRings (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingCmps,
- &Dev->RingDesc.RingCmpsDmaDesc
- );
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingReqs,
- &Dev->RingDesc.RingReqsDmaDesc
- );
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingState,
- &Dev->RingDesc.RingStateDmaDesc
- );
- }
- STATIC
- EFI_STATUS
- PvScsiSetupRings (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- union {
- PVSCSI_CMD_DESC_SETUP_RINGS Cmd;
- UINT32 Uint32;
- } AlignedCmd;
- PVSCSI_CMD_DESC_SETUP_RINGS *Cmd;
- Cmd = &AlignedCmd.Cmd;
- ZeroMem (Cmd, sizeof (*Cmd));
- Cmd->ReqRingNumPages = 1;
- Cmd->CmpRingNumPages = 1;
- Cmd->RingsStatePPN = RShiftU64 (
- Dev->RingDesc.RingStateDmaDesc.DeviceAddress,
- EFI_PAGE_SHIFT
- );
- Cmd->ReqRingPPNs[0] = RShiftU64 (
- Dev->RingDesc.RingReqsDmaDesc.DeviceAddress,
- EFI_PAGE_SHIFT
- );
- Cmd->CmpRingPPNs[0] = RShiftU64 (
- Dev->RingDesc.RingCmpsDmaDesc.DeviceAddress,
- EFI_PAGE_SHIFT
- );
- STATIC_ASSERT (
- sizeof (*Cmd) % sizeof (UINT32) == 0,
- "Cmd must be multiple of 32-bit words"
- );
- return PvScsiWriteCmdDesc (
- Dev,
- PvScsiCmdSetupRings,
- (UINT32 *)Cmd,
- sizeof (*Cmd) / sizeof (UINT32)
- );
- }
- STATIC
- EFI_STATUS
- PvScsiInit (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- EFI_STATUS Status;
- //
- // Init configuration
- //
- Dev->MaxTarget = PcdGet8 (PcdPvScsiMaxTargetLimit);
- Dev->MaxLun = PcdGet8 (PcdPvScsiMaxLunLimit);
- Dev->WaitForCmpStallInUsecs = PcdGet32 (PcdPvScsiWaitForCmpStallInUsecs);
- //
- // Set PCI Attributes
- //
- Status = PvScsiSetPciAttributes (Dev);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Reset adapter
- //
- Status = PvScsiResetAdapter (Dev);
- if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
- }
- //
- // Init PVSCSI rings
- //
- Status = PvScsiInitRings (Dev);
- if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
- }
- //
- // Allocate DMA communication buffer
- //
- Status = PvScsiAllocateSharedPages (
- Dev,
- EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),
- (VOID **)&Dev->DmaBuf,
- &Dev->DmaBufDmaDesc
- );
- if (EFI_ERROR (Status)) {
- goto FreeRings;
- }
- //
- // Setup rings against device
- //
- Status = PvScsiSetupRings (Dev);
- if (EFI_ERROR (Status)) {
- goto FreeDmaCommBuffer;
- }
- //
- // Populate the exported interface's attributes
- //
- Dev->PassThru.Mode = &Dev->PassThruMode;
- Dev->PassThru.PassThru = &PvScsiPassThru;
- Dev->PassThru.GetNextTargetLun = &PvScsiGetNextTargetLun;
- Dev->PassThru.BuildDevicePath = &PvScsiBuildDevicePath;
- Dev->PassThru.GetTargetLun = &PvScsiGetTargetLun;
- Dev->PassThru.ResetChannel = &PvScsiResetChannel;
- Dev->PassThru.ResetTargetLun = &PvScsiResetTargetLun;
- Dev->PassThru.GetNextTarget = &PvScsiGetNextTarget;
- //
- // AdapterId is a target for which no handle will be created during bus scan.
- // Prevent any conflict with real devices.
- //
- Dev->PassThruMode.AdapterId = MAX_UINT32;
- //
- // Set both physical and logical attributes for non-RAID SCSI channel
- //
- Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
- EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
- //
- // No restriction on transfer buffer alignment
- //
- Dev->PassThruMode.IoAlign = 0;
- return EFI_SUCCESS;
- FreeDmaCommBuffer:
- PvScsiFreeSharedPages (
- Dev,
- EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),
- Dev->DmaBuf,
- &Dev->DmaBufDmaDesc
- );
- FreeRings:
- PvScsiFreeRings (Dev);
- RestorePciAttributes:
- PvScsiRestorePciAttributes (Dev);
- return Status;
- }
- STATIC
- VOID
- PvScsiUninit (
- IN OUT PVSCSI_DEV *Dev
- )
- {
- //
- // Reset device to:
- // - Make device stop processing all requests.
- // - Stop device usage of the rings.
- //
- // This is required to safely free the DMA communication buffer
- // and the rings.
- //
- PvScsiResetAdapter (Dev);
- //
- // Free DMA communication buffer
- //
- PvScsiFreeSharedPages (
- Dev,
- EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),
- Dev->DmaBuf,
- &Dev->DmaBufDmaDesc
- );
- PvScsiFreeRings (Dev);
- PvScsiRestorePciAttributes (Dev);
- }
- /**
- Event notification called by ExitBootServices()
- **/
- STATIC
- VOID
- EFIAPI
- PvScsiExitBoot (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- PVSCSI_DEV *Dev;
- Dev = Context;
- DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
- //
- // Reset the device to stop device usage of the rings.
- //
- // We allocated said rings in EfiBootServicesData type memory, and code
- // executing after ExitBootServices() is permitted to overwrite it.
- //
- PvScsiResetAdapter (Dev);
- }
- //
- // Driver Binding
- //
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- 0,
- sizeof (Pci) / sizeof (UINT32),
- &Pci
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- if ((Pci.Hdr.VendorId != PCI_VENDOR_ID_VMWARE) ||
- (Pci.Hdr.DeviceId != PCI_DEVICE_ID_VMWARE_PVSCSI))
- {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
- Status = EFI_SUCCESS;
- Done:
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- return Status;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- PVSCSI_DEV *Dev;
- EFI_STATUS Status;
- Dev = (PVSCSI_DEV *)AllocateZeroPool (sizeof (*Dev));
- if (Dev == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&Dev->PciIo,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- goto FreePvScsi;
- }
- Status = PvScsiInit (Dev);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
- Status = gBS->CreateEvent (
- EVT_SIGNAL_EXIT_BOOT_SERVICES,
- TPL_CALLBACK,
- &PvScsiExitBoot,
- Dev,
- &Dev->ExitBoot
- );
- if (EFI_ERROR (Status)) {
- goto UninitDev;
- }
- //
- // Setup complete, attempt to export the driver instance's PassThru interface
- //
- Dev->Signature = PVSCSI_SIG;
- Status = gBS->InstallProtocolInterface (
- &ControllerHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &Dev->PassThru
- );
- if (EFI_ERROR (Status)) {
- goto CloseExitBoot;
- }
- return EFI_SUCCESS;
- CloseExitBoot:
- gBS->CloseEvent (Dev->ExitBoot);
- UninitDev:
- PvScsiUninit (Dev);
- ClosePciIo:
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- FreePvScsi:
- FreePool (Dev);
- return Status;
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
- {
- EFI_STATUS Status;
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
- PVSCSI_DEV *Dev;
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- (VOID **)&PassThru,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Dev = PVSCSI_FROM_PASS_THRU (PassThru);
- Status = gBS->UninstallProtocolInterface (
- ControllerHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- &Dev->PassThru
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- gBS->CloseEvent (Dev->ExitBoot);
- PvScsiUninit (Dev);
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiPciIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- FreePool (Dev);
- return EFI_SUCCESS;
- }
- STATIC EFI_DRIVER_BINDING_PROTOCOL mPvScsiDriverBinding = {
- &PvScsiDriverBindingSupported,
- &PvScsiDriverBindingStart,
- &PvScsiDriverBindingStop,
- PVSCSI_BINDING_VERSION,
- NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2()
- NULL // DriverBindingHandle, filled as well
- };
- //
- // Component Name
- //
- STATIC EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
- { "eng;en", L"PVSCSI Host Driver" },
- { NULL, NULL }
- };
- STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName;
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiGetDriverName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN CHAR8 *Language,
- OUT CHAR16 **DriverName
- )
- {
- return LookupUnicodeString2 (
- Language,
- This->SupportedLanguages,
- mDriverNameTable,
- DriverName,
- (BOOLEAN)(This == &mComponentName) // Iso639Language
- );
- }
- STATIC
- EFI_STATUS
- EFIAPI
- PvScsiGetDeviceName (
- IN EFI_COMPONENT_NAME_PROTOCOL *This,
- IN EFI_HANDLE DeviceHandle,
- IN EFI_HANDLE ChildHandle,
- IN CHAR8 *Language,
- OUT CHAR16 **ControllerName
- )
- {
- return EFI_UNSUPPORTED;
- }
- STATIC EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
- &PvScsiGetDriverName,
- &PvScsiGetDeviceName,
- "eng" // SupportedLanguages, ISO 639-2 language codes
- };
- STATIC EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
- (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&PvScsiGetDriverName,
- (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&PvScsiGetDeviceName,
- "en" // SupportedLanguages, RFC 4646 language codes
- };
- //
- // Entry Point
- //
- EFI_STATUS
- EFIAPI
- PvScsiEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- return EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &mPvScsiDriverBinding,
- ImageHandle,
- &mComponentName,
- &mComponentName2
- );
- }
|