/*++ | |
Copyright (c) 2006, Intel Corporation | |
All rights reserved. This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
Module Name: | |
scsibus.c | |
Abstract: | |
Revision History | |
--*/ | |
#include "ScsiBus.h" | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingSupported ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
); | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingStart ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
); | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingStop ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN UINTN NumberOfChildren, | |
IN EFI_HANDLE *ChildHandleBuffer | |
); | |
EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = { | |
SCSIBusDriverBindingSupported, | |
SCSIBusDriverBindingStart, | |
SCSIBusDriverBindingStop, | |
0x10, | |
NULL, | |
NULL | |
}; | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingSupported ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
) | |
/*++ | |
Routine Description: | |
Arguments: | |
Returns: | |
--*/ | |
// TODO: This - add argument and description to function comment | |
// TODO: Controller - add argument and description to function comment | |
// TODO: RemainingDevicePath - add argument and description to function comment | |
// TODO: EFI_UNSUPPORTED - add return value to function comment | |
// TODO: EFI_UNSUPPORTED - add return value to function comment | |
// TODO: EFI_SUCCESS - add return value to function comment | |
{ | |
EFI_STATUS Status; | |
// | |
// If RemainingDevicePath is not NULL, it should verify that the first device | |
// path node in RemainingDevicePath is an ATAPI Device path node. | |
// | |
if (RemainingDevicePath != NULL) { | |
if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) || | |
(RemainingDevicePath->SubType != MSG_ATAPI_DP) || | |
(DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) { | |
return EFI_UNSUPPORTED; | |
} | |
} | |
// | |
// check for the existence of SCSI Pass Thru Protocol | |
// | |
Status = gBS->OpenProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
NULL, | |
This->DriverBindingHandle, | |
Controller, | |
EFI_OPEN_PROTOCOL_TEST_PROTOCOL | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { | |
return EFI_UNSUPPORTED; | |
} | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingStart ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
) | |
/*++ | |
Routine Description: | |
Arguments: | |
Returns: | |
--*/ | |
// TODO: This - add argument and description to function comment | |
// TODO: Controller - add argument and description to function comment | |
// TODO: RemainingDevicePath - add argument and description to function comment | |
{ | |
EFI_STATUS Status; | |
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; | |
EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; | |
UINT32 StartPun; | |
UINT64 StartLun; | |
UINT32 Pun; | |
UINT64 Lun; | |
BOOLEAN ScanOtherPuns; | |
StartPun = 0; | |
StartLun = 0; | |
Status = gBS->OpenProtocol ( | |
Controller, | |
&gEfiDevicePathProtocolGuid, | |
(VOID **) &ParentDevicePath, | |
This->DriverBindingHandle, | |
Controller, | |
EFI_OPEN_PROTOCOL_BY_DRIVER | |
); | |
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { | |
return Status; | |
} | |
// | |
// Consume SCSI Pass Thru protocol. | |
// | |
Status = gBS->OpenProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
(VOID **) &ScsiPassThru, | |
This->DriverBindingHandle, | |
Controller, | |
EFI_OPEN_PROTOCOL_BY_DRIVER | |
); | |
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiDevicePathProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
return Status; | |
} | |
if (RemainingDevicePath == NULL) { | |
StartPun = 0xFFFFFFFF; | |
StartLun = 0; | |
} else { | |
ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun); | |
} | |
for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) { | |
if (StartPun == 0xFFFFFFFF) { | |
// | |
// Remaining Device Path is NULL, scan all the possible Puns in the | |
// SCSI Channel. | |
// | |
Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun); | |
if (EFI_ERROR (Status)) { | |
// | |
// no legal Pun and Lun found any more | |
// | |
break; | |
} | |
} else { | |
// | |
// Remaining Device Path is not NULL, only scan the specified Pun. | |
// | |
Pun = StartPun; | |
Lun = StartLun; | |
ScanOtherPuns = FALSE; | |
} | |
// | |
// Avoid creating handle for the host adapter. | |
// | |
if (Pun == ScsiPassThru->Mode->AdapterId) { | |
continue; | |
} | |
// | |
// Scan for the scsi device, if it attaches to the scsi bus, | |
// then create handle and install scsi i/o protocol. | |
// | |
Status = ScsiScanCreateDevice (This, Controller, Pun, Lun, ScsiPassThru, ParentDevicePath); | |
} | |
return Status; | |
} | |
EFI_STATUS | |
EFIAPI | |
SCSIBusDriverBindingStop ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN UINTN NumberOfChildren, | |
IN EFI_HANDLE *ChildHandleBuffer | |
) | |
/*++ | |
Routine Description: | |
Arguments: | |
Returns: | |
--*/ | |
// TODO: This - add argument and description to function comment | |
// TODO: Controller - add argument and description to function comment | |
// TODO: NumberOfChildren - add argument and description to function comment | |
// TODO: ChildHandleBuffer - add argument and description to function comment | |
// TODO: EFI_SUCCESS - add return value to function comment | |
// TODO: EFI_DEVICE_ERROR - add return value to function comment | |
// TODO: EFI_SUCCESS - add return value to function comment | |
{ | |
EFI_STATUS Status; | |
BOOLEAN AllChildrenStopped; | |
UINTN Index; | |
EFI_SCSI_IO_PROTOCOL *ScsiIo; | |
SCSI_IO_DEV *ScsiIoDevice; | |
EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; | |
if (NumberOfChildren == 0) { | |
// | |
// Close the bus driver | |
// | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiDevicePathProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
return EFI_SUCCESS; | |
} | |
AllChildrenStopped = TRUE; | |
for (Index = 0; Index < NumberOfChildren; Index++) { | |
Status = gBS->OpenProtocol ( | |
ChildHandleBuffer[Index], | |
&gEfiScsiIoProtocolGuid, | |
(VOID **) &ScsiIo, | |
This->DriverBindingHandle, | |
Controller, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
if (EFI_ERROR (Status)) { | |
AllChildrenStopped = FALSE; | |
continue; | |
} | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo); | |
// | |
// Close the child handle | |
// | |
Status = gBS->CloseProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
This->DriverBindingHandle, | |
ChildHandleBuffer[Index] | |
); | |
Status = gBS->UninstallMultipleProtocolInterfaces ( | |
ChildHandleBuffer[Index], | |
&gEfiDevicePathProtocolGuid, | |
ScsiIoDevice->DevicePath, | |
&gEfiScsiIoProtocolGuid, | |
&ScsiIoDevice->ScsiIo, | |
NULL | |
); | |
if (EFI_ERROR (Status)) { | |
AllChildrenStopped = FALSE; | |
gBS->OpenProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
(VOID **) &ScsiPassThru, | |
This->DriverBindingHandle, | |
ChildHandleBuffer[Index], | |
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
); | |
} else { | |
gBS->FreePool (ScsiIoDevice); | |
} | |
} | |
if (!AllChildrenStopped) { | |
return EFI_DEVICE_ERROR; | |
} | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
ScsiGetDeviceType ( | |
IN EFI_SCSI_IO_PROTOCOL *This, | |
OUT UINT8 *DeviceType | |
) | |
/*++ | |
Routine Description: | |
Retrieves the device type information of the SCSI Controller. | |
Arguments: | |
This - Protocol instance pointer. | |
DeviceType - A pointer to the device type information | |
retrieved from the SCSI Controller. | |
Returns: | |
EFI_SUCCESS - Retrieves the device type information successfully. | |
EFI_INVALID_PARAMETER - The DeviceType is NULL. | |
--*/ | |
{ | |
SCSI_IO_DEV *ScsiIoDevice; | |
if (DeviceType == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); | |
*DeviceType = ScsiIoDevice->ScsiDeviceType; | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
ScsiGetDeviceLocation ( | |
IN EFI_SCSI_IO_PROTOCOL *This, | |
OUT UINT8 **Target, | |
OUT UINT64 *Lun | |
) | |
/*++ | |
Routine Description: | |
Retrieves the device location in the SCSI channel. | |
Arguments: | |
This - Protocol instance pointer. | |
Target - A pointer to the Target ID of a SCSI device | |
on the SCSI channel. | |
Lun - A pointer to the LUN of the SCSI device on | |
the SCSI channel. | |
Returns: | |
EFI_SUCCESS - Retrieves the device location successfully. | |
EFI_INVALID_PARAMETER - The Target or Lun is NULL. | |
--*/ | |
{ | |
SCSI_IO_DEV *ScsiIoDevice; | |
if (Target == NULL || Lun == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); | |
*Target = (UINT8 *) (UINTN) ScsiIoDevice->Pun; | |
*Lun = ScsiIoDevice->Lun; | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
ScsiResetBus ( | |
IN EFI_SCSI_IO_PROTOCOL *This | |
) | |
/*++ | |
Routine Description: | |
Resets the SCSI Bus that the SCSI Controller is attached to. | |
Arguments: | |
This - Protocol instance pointer. | |
Returns: | |
EFI_SUCCESS - The SCSI bus is reset successfully. | |
EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus. | |
EFI_UNSUPPORTED - The bus reset operation is not supported by the | |
SCSI Host Controller. | |
EFI_TIMEOUT - A timeout occurred while attempting to reset | |
the SCSI bus. | |
--*/ | |
{ | |
SCSI_IO_DEV *ScsiIoDevice; | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); | |
return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru); | |
} | |
EFI_STATUS | |
EFIAPI | |
ScsiResetDevice ( | |
IN EFI_SCSI_IO_PROTOCOL *This | |
) | |
/*++ | |
Routine Description: | |
Resets the SCSI Controller that the device handle specifies. | |
Arguments: | |
This - Protocol instance pointer. | |
Returns: | |
EFI_SUCCESS - Reset the SCSI controller successfully. | |
EFI_DEVICE_ERROR - Errors are encountered when resetting the | |
SCSI Controller. | |
EFI_UNSUPPORTED - The SCSI bus does not support a device | |
reset operation. | |
EFI_TIMEOUT - A timeout occurred while attempting to | |
reset the SCSI Controller. | |
--*/ | |
{ | |
SCSI_IO_DEV *ScsiIoDevice; | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); | |
return ScsiIoDevice->ScsiPassThru->ResetTarget ( | |
ScsiIoDevice->ScsiPassThru, | |
ScsiIoDevice->Pun, | |
ScsiIoDevice->Lun | |
); | |
} | |
EFI_STATUS | |
EFIAPI | |
ScsiExecuteSCSICommand ( | |
IN EFI_SCSI_IO_PROTOCOL *This, | |
IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, | |
IN EFI_EVENT Event OPTIONAL | |
) | |
/*++ | |
Routine Description: | |
Sends a SCSI Request Packet to the SCSI Controller for execution. | |
Arguments: | |
This - Protocol instance pointer. | |
Packet - The SCSI request packet to send to the SCSI | |
Controller specified by the device handle. | |
Event - If the SCSI bus where the SCSI device is attached | |
does not support non-blocking I/O, then Event is | |
ignored, and blocking I/O is performed. | |
If Event is NULL, then blocking I/O is performed. | |
If Event is not NULL and non-blocking I/O is | |
supported, then non-blocking I/O is performed, | |
and Event will be signaled when the SCSI Request | |
Packet completes. | |
Returns: | |
EFI_SUCCESS - The SCSI Request Packet was sent by the host | |
successfully, and TransferLength bytes were | |
transferred to/from DataBuffer.See | |
HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order | |
for additional status information. | |
EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
but the entire DataBuffer could not be transferred. | |
The actual number of bytes transferred is returned | |
in TransferLength. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in | |
that order for additional status information. | |
EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
there are too many SCSI Command Packets already | |
queued.The caller may retry again later. | |
EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
the SCSI Request Packet. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in | |
that order for additional status information. | |
EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
The SCSI Request Packet was not sent, so no | |
additional status information is available. | |
EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
is not supported by the SCSI initiator(i.e., SCSI | |
Host Controller). The SCSI Request Packet was not | |
sent, so no additional status information is | |
available. | |
EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
Request Packet to execute. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in | |
that order for additional status information. | |
--*/ | |
{ | |
SCSI_IO_DEV *ScsiIoDevice; | |
EFI_STATUS Status; | |
EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *RequestPacket; | |
if (Packet == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); | |
RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet; | |
Status = ScsiIoDevice->ScsiPassThru->PassThru ( | |
ScsiIoDevice->ScsiPassThru, | |
ScsiIoDevice->Pun, | |
ScsiIoDevice->Lun, | |
RequestPacket, | |
Event | |
); | |
return Status; | |
} | |
EFI_STATUS | |
ScsiScanCreateDevice ( | |
EFI_DRIVER_BINDING_PROTOCOL *This, | |
EFI_HANDLE Controller, | |
UINT32 Pun, | |
UINT64 Lun, | |
EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, | |
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath | |
) | |
/*++ | |
Routine Description: | |
TODO: Add function description | |
Arguments: | |
This - TODO: add argument description | |
Controller - TODO: add argument description | |
Pun - TODO: add argument description | |
Lun - TODO: add argument description | |
ScsiPassThru - TODO: add argument description | |
ParentDevicePath - TODO: add argument description | |
Returns: | |
EFI_SUCCESS - TODO: Add description for return value | |
EFI_OUT_OF_RESOURCES - TODO: Add description for return value | |
EFI_SUCCESS - TODO: Add description for return value | |
--*/ | |
{ | |
EFI_STATUS Status; | |
SCSI_IO_DEV *ScsiIoDevice; | |
EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath; | |
Status = gBS->AllocatePool ( | |
EfiBootServicesData, | |
sizeof (SCSI_IO_DEV), | |
(VOID **) &ScsiIoDevice | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV)); | |
ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; | |
ScsiIoDevice->ScsiPassThru = ScsiPassThru; | |
ScsiIoDevice->Pun = Pun; | |
ScsiIoDevice->Lun = Lun; | |
ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType; | |
ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation; | |
ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus; | |
ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; | |
ScsiIoDevice->ScsiIo.ExecuteSCSICommand = ScsiExecuteSCSICommand; | |
if (!DiscoverScsiDevice (ScsiIoDevice)) { | |
gBS->FreePool (ScsiIoDevice); | |
return EFI_SUCCESS; | |
} | |
// | |
// Set Device Path | |
// | |
Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath ( | |
ScsiIoDevice->ScsiPassThru, | |
ScsiIoDevice->Pun, | |
ScsiIoDevice->Lun, | |
&ScsiDevicePath | |
); | |
if (Status == EFI_OUT_OF_RESOURCES) { | |
gBS->FreePool (ScsiIoDevice); | |
return Status; | |
} | |
ScsiIoDevice->DevicePath = AppendDevicePathNode ( | |
ParentDevicePath, | |
ScsiDevicePath | |
); | |
// | |
// The memory space for ScsiDevicePath is allocated in | |
// ScsiPassThru->BuildDevicePath() function; It is no longer used | |
// after EfiAppendDevicePathNode,so free the memory it occupies. | |
// | |
gBS->FreePool (ScsiDevicePath); | |
if (ScsiIoDevice->DevicePath == NULL) { | |
gBS->FreePool (ScsiIoDevice); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&ScsiIoDevice->Handle, | |
&gEfiDevicePathProtocolGuid, | |
ScsiIoDevice->DevicePath, | |
&gEfiScsiIoProtocolGuid, | |
&ScsiIoDevice->ScsiIo, | |
NULL | |
); | |
if (EFI_ERROR (Status)) { | |
gBS->FreePool (ScsiIoDevice); | |
} else { | |
gBS->OpenProtocol ( | |
Controller, | |
&gEfiScsiPassThruProtocolGuid, | |
(VOID **) &ScsiPassThru, | |
This->DriverBindingHandle, | |
ScsiIoDevice->Handle, | |
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
); | |
} | |
return EFI_SUCCESS; | |
} | |
BOOLEAN | |
DiscoverScsiDevice ( | |
SCSI_IO_DEV *ScsiIoDevice | |
) | |
/*++ | |
Routine Description: | |
TODO: Add function description | |
Arguments: | |
ScsiIoDevice - TODO: add argument description | |
Returns: | |
TODO: add return values | |
--*/ | |
{ | |
EFI_STATUS Status; | |
EFI_SCSI_INQUIRY_DATA InquiryData; | |
UINT32 InquiryDataLength; | |
EFI_SCSI_SENSE_DATA SenseData; | |
UINT8 SenseDataLength; | |
UINT8 HostAdapterStatus; | |
UINT8 TargetStatus; | |
HostAdapterStatus = 0; | |
TargetStatus = 0; | |
// | |
// Using Inquiry command to scan for the device | |
// | |
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); | |
SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA); | |
Status = SubmitInquiryCommand ( | |
&ScsiIoDevice->ScsiIo, | |
EfiScsiStallSeconds (1), | |
(VOID *) &SenseData, | |
&SenseDataLength, | |
&HostAdapterStatus, | |
&TargetStatus, | |
(VOID *) &InquiryData, | |
&InquiryDataLength, | |
FALSE | |
); | |
if (EFI_ERROR (Status)) { | |
// | |
// ParseSenseData (&SenseData,SenseDataLength); | |
// | |
return FALSE; | |
} | |
// | |
// Retrieved inquiry data successfully | |
// | |
if ((InquiryData.Peripheral_Qualifier != 0) && | |
(InquiryData.Peripheral_Qualifier != 3)) { | |
return FALSE; | |
} | |
if (InquiryData.Peripheral_Qualifier == 3) { | |
if (InquiryData.Peripheral_Type != 0x1f) { | |
return FALSE; | |
} | |
} | |
if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) { | |
return FALSE; | |
} | |
// | |
// valid device type and peripheral qualifier combination. | |
// | |
ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type; | |
ScsiIoDevice->RemovableDevice = InquiryData.RMB; | |
if (InquiryData.Version == 0) { | |
ScsiIoDevice->ScsiVersion = 0; | |
} else { | |
// | |
// ANSI-approved version | |
// | |
ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03); | |
} | |
return TRUE; | |
} |