Patch so the tree will compile
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 scsibus.c
15
16 Abstract:
17
18
19 Revision History
20 --*/
21
22 //
23 // The package level header files this module uses
24 //
25 #include <PiDxe.h>
26
27 //
28 // The protocols, PPI and GUID defintions for this module
29 //
30 #include <Protocol/ScsiPassThru.h>
31 #include <Protocol/ScsiIo.h>
32 #include <Protocol/ComponentName.h>
33 #include <Protocol/DriverBinding.h>
34 #include <Protocol/DevicePath.h>
35 //
36 // The Library classes this module consumes
37 //
38 #include <Library/DebugLib.h>
39 #include <Library/UefiDriverEntryPoint.h>
40 #include <Library/UefiLib.h>
41 #include <Library/BaseMemoryLib.h>
42 #include <Library/ScsiLib.h>
43 #include <Library/UefiBootServicesTableLib.h>
44 #include <Library/DevicePathLib.h>
45
46 #include "ScsiBus.h"
47
48 EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
49 SCSIBusDriverBindingSupported,
50 SCSIBusDriverBindingStart,
51 SCSIBusDriverBindingStop,
52 0xa,
53 NULL,
54 NULL
55 };
56
57 /**
58 The user Entry Point for module ScsiBus. The user code starts with this function.
59
60 @param[in] ImageHandle The firmware allocated handle for the EFI image.
61 @param[in] SystemTable A pointer to the EFI System Table.
62
63 @retval EFI_SUCCESS The entry point is executed successfully.
64 @retval other Some error occurs when executing this entry point.
65
66 **/
67 EFI_STATUS
68 EFIAPI
69 InitializeScsiBus(
70 IN EFI_HANDLE ImageHandle,
71 IN EFI_SYSTEM_TABLE *SystemTable
72 )
73 {
74 EFI_STATUS Status;
75
76 //
77 // Install driver model protocol(s).
78 //
79 Status = EfiLibInstallAllDriverProtocols (
80 ImageHandle,
81 SystemTable,
82 &gSCSIBusDriverBinding,
83 ImageHandle,
84 &gScsiBusComponentName,
85 NULL,
86 NULL
87 );
88 ASSERT_EFI_ERROR (Status);
89
90
91 return Status;
92 }
93
94 EFI_STATUS
95 EFIAPI
96 SCSIBusDriverBindingSupported (
97 IN EFI_DRIVER_BINDING_PROTOCOL *This,
98 IN EFI_HANDLE Controller,
99 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
100 )
101 /*++
102
103 Routine Description:
104
105 Arguments:
106
107 Returns:
108
109 --*/
110 // TODO: This - add argument and description to function comment
111 // TODO: Controller - add argument and description to function comment
112 // TODO: RemainingDevicePath - add argument and description to function comment
113 // TODO: EFI_UNSUPPORTED - add return value to function comment
114 // TODO: EFI_UNSUPPORTED - add return value to function comment
115 // TODO: EFI_SUCCESS - add return value to function comment
116 {
117 EFI_STATUS Status;
118
119 //
120 // If RemainingDevicePath is not NULL, it should verify that the first device
121 // path node in RemainingDevicePath is an ATAPI Device path node.
122 //
123 if (RemainingDevicePath != NULL) {
124 if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||
125 (RemainingDevicePath->SubType != MSG_ATAPI_DP) ||
126 (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) {
127 return EFI_UNSUPPORTED;
128 }
129 }
130 //
131 // check for the existence of SCSI Pass Thru Protocol
132 //
133 Status = gBS->OpenProtocol (
134 Controller,
135 &gEfiScsiPassThruProtocolGuid,
136 NULL,
137 This->DriverBindingHandle,
138 Controller,
139 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
140 );
141 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
142 return EFI_UNSUPPORTED;
143 }
144
145 return EFI_SUCCESS;
146 }
147
148 EFI_STATUS
149 EFIAPI
150 SCSIBusDriverBindingStart (
151 IN EFI_DRIVER_BINDING_PROTOCOL *This,
152 IN EFI_HANDLE Controller,
153 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
154 )
155 /*++
156
157 Routine Description:
158
159 Arguments:
160
161 Returns:
162
163 --*/
164 // TODO: This - add argument and description to function comment
165 // TODO: Controller - add argument and description to function comment
166 // TODO: RemainingDevicePath - add argument and description to function comment
167 {
168 EFI_STATUS Status;
169 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
170 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;
171 UINT32 StartPun;
172 UINT64 StartLun;
173 UINT32 Pun;
174 UINT64 Lun;
175 BOOLEAN ScanOtherPuns;
176
177 StartPun = 0;
178 StartLun = 0;
179 Status = gBS->OpenProtocol (
180 Controller,
181 &gEfiDevicePathProtocolGuid,
182 (VOID **) &ParentDevicePath,
183 This->DriverBindingHandle,
184 Controller,
185 EFI_OPEN_PROTOCOL_BY_DRIVER
186 );
187 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
188 return Status;
189 }
190
191 //
192 // Consume SCSI Pass Thru protocol.
193 //
194 Status = gBS->OpenProtocol (
195 Controller,
196 &gEfiScsiPassThruProtocolGuid,
197 (VOID **) &ScsiPassThru,
198 This->DriverBindingHandle,
199 Controller,
200 EFI_OPEN_PROTOCOL_BY_DRIVER
201 );
202 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
203 gBS->CloseProtocol (
204 Controller,
205 &gEfiDevicePathProtocolGuid,
206 This->DriverBindingHandle,
207 Controller
208 );
209 return Status;
210 }
211
212 if (RemainingDevicePath == NULL) {
213 StartPun = 0xFFFFFFFF;
214 StartLun = 0;
215 } else {
216 ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun);
217 }
218
219 for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) {
220
221 if (StartPun == 0xFFFFFFFF) {
222 //
223 // Remaining Device Path is NULL, scan all the possible Puns in the
224 // SCSI Channel.
225 //
226 Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun);
227 if (EFI_ERROR (Status)) {
228 //
229 // no legal Pun and Lun found any more
230 //
231 break;
232 }
233 } else {
234 //
235 // Remaining Device Path is not NULL, only scan the specified Pun.
236 //
237 Pun = StartPun;
238 Lun = StartLun;
239 ScanOtherPuns = FALSE;
240 }
241
242 //
243 // Avoid creating handle for the host adapter.
244 //
245 if (Pun == ScsiPassThru->Mode->AdapterId) {
246 continue;
247 }
248
249 //
250 // Scan for the scsi device, if it attaches to the scsi bus,
251 // then create handle and install scsi i/o protocol.
252 //
253 Status = ScsiScanCreateDevice (This, Controller, Pun, Lun, ScsiPassThru, ParentDevicePath);
254 }
255
256 return Status;
257 }
258
259 EFI_STATUS
260 EFIAPI
261 SCSIBusDriverBindingStop (
262 IN EFI_DRIVER_BINDING_PROTOCOL *This,
263 IN EFI_HANDLE Controller,
264 IN UINTN NumberOfChildren,
265 IN EFI_HANDLE *ChildHandleBuffer
266 )
267 /*++
268
269 Routine Description:
270
271 Arguments:
272
273 Returns:
274
275 --*/
276 // TODO: This - add argument and description to function comment
277 // TODO: Controller - add argument and description to function comment
278 // TODO: NumberOfChildren - add argument and description to function comment
279 // TODO: ChildHandleBuffer - add argument and description to function comment
280 // TODO: EFI_SUCCESS - add return value to function comment
281 // TODO: EFI_DEVICE_ERROR - add return value to function comment
282 // TODO: EFI_SUCCESS - add return value to function comment
283 {
284 EFI_STATUS Status;
285 BOOLEAN AllChildrenStopped;
286 UINTN Index;
287 EFI_SCSI_IO_PROTOCOL *ScsiIo;
288 SCSI_IO_DEV *ScsiIoDevice;
289 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;
290
291 if (NumberOfChildren == 0) {
292 //
293 // Close the bus driver
294 //
295 gBS->CloseProtocol (
296 Controller,
297 &gEfiScsiPassThruProtocolGuid,
298 This->DriverBindingHandle,
299 Controller
300 );
301 gBS->CloseProtocol (
302 Controller,
303 &gEfiDevicePathProtocolGuid,
304 This->DriverBindingHandle,
305 Controller
306 );
307
308 return EFI_SUCCESS;
309 }
310
311 AllChildrenStopped = TRUE;
312
313 for (Index = 0; Index < NumberOfChildren; Index++) {
314
315 Status = gBS->OpenProtocol (
316 ChildHandleBuffer[Index],
317 &gEfiScsiIoProtocolGuid,
318 (VOID **) &ScsiIo,
319 This->DriverBindingHandle,
320 Controller,
321 EFI_OPEN_PROTOCOL_GET_PROTOCOL
322 );
323 if (EFI_ERROR (Status)) {
324 AllChildrenStopped = FALSE;
325 continue;
326 }
327
328 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);
329 //
330 // Close the child handle
331 //
332 Status = gBS->CloseProtocol (
333 Controller,
334 &gEfiScsiPassThruProtocolGuid,
335 This->DriverBindingHandle,
336 ChildHandleBuffer[Index]
337 );
338
339 Status = gBS->UninstallMultipleProtocolInterfaces (
340 ChildHandleBuffer[Index],
341 &gEfiDevicePathProtocolGuid,
342 ScsiIoDevice->DevicePath,
343 &gEfiScsiIoProtocolGuid,
344 &ScsiIoDevice->ScsiIo,
345 NULL
346 );
347 if (EFI_ERROR (Status)) {
348 AllChildrenStopped = FALSE;
349 gBS->OpenProtocol (
350 Controller,
351 &gEfiScsiPassThruProtocolGuid,
352 (VOID **) &ScsiPassThru,
353 This->DriverBindingHandle,
354 ChildHandleBuffer[Index],
355 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
356 );
357 } else {
358 gBS->FreePool (ScsiIoDevice);
359 }
360 }
361
362 if (!AllChildrenStopped) {
363 return EFI_DEVICE_ERROR;
364 }
365
366 return EFI_SUCCESS;
367 }
368
369 EFI_STATUS
370 EFIAPI
371 ScsiGetDeviceType (
372 IN EFI_SCSI_IO_PROTOCOL *This,
373 OUT UINT8 *DeviceType
374 )
375 /*++
376
377 Routine Description:
378 Retrieves the device type information of the SCSI Controller.
379
380 Arguments:
381 This - Protocol instance pointer.
382 DeviceType - A pointer to the device type information
383 retrieved from the SCSI Controller.
384
385 Returns:
386 EFI_SUCCESS - Retrieves the device type information successfully.
387 EFI_INVALID_PARAMETER - The DeviceType is NULL.
388 --*/
389 {
390 SCSI_IO_DEV *ScsiIoDevice;
391
392 if (DeviceType == NULL) {
393 return EFI_INVALID_PARAMETER;
394 }
395
396 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
397 *DeviceType = ScsiIoDevice->ScsiDeviceType;
398 return EFI_SUCCESS;
399 }
400
401 STATIC
402 EFI_STATUS
403 EFIAPI
404 ScsiGetDeviceLocation (
405 IN EFI_SCSI_IO_PROTOCOL *This,
406 OUT UINT32 *Target,
407 OUT UINT64 *Lun
408 )
409 /*++
410 Routine Description:
411 Retrieves the device location in the SCSI channel.
412
413 Arguments:
414 This - Protocol instance pointer.
415 Target - A pointer to the Target ID of a SCSI device
416 on the SCSI channel.
417 Lun - A pointer to the LUN of the SCSI device on
418 the SCSI channel.
419
420 Returns:
421 EFI_SUCCESS - Retrieves the device location successfully.
422 EFI_INVALID_PARAMETER - The Target or Lun is NULL.
423 --*/
424 {
425 SCSI_IO_DEV *ScsiIoDevice;
426
427 if (Target == NULL || Lun == NULL) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
432
433 *Target = ScsiIoDevice->Pun;
434 *Lun = ScsiIoDevice->Lun;
435
436 return EFI_SUCCESS;
437 }
438
439 EFI_STATUS
440 EFIAPI
441 ScsiResetBus (
442 IN EFI_SCSI_IO_PROTOCOL *This
443 )
444 /*++
445
446 Routine Description:
447 Resets the SCSI Bus that the SCSI Controller is attached to.
448
449 Arguments:
450 This - Protocol instance pointer.
451
452 Returns:
453 EFI_SUCCESS - The SCSI bus is reset successfully.
454 EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus.
455 EFI_UNSUPPORTED - The bus reset operation is not supported by the
456 SCSI Host Controller.
457 EFI_TIMEOUT - A timeout occurred while attempting to reset
458 the SCSI bus.
459 --*/
460 {
461 SCSI_IO_DEV *ScsiIoDevice;
462
463 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
464
465 return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);
466
467 }
468
469 EFI_STATUS
470 EFIAPI
471 ScsiResetDevice (
472 IN EFI_SCSI_IO_PROTOCOL *This
473 )
474 /*++
475
476 Routine Description:
477 Resets the SCSI Controller that the device handle specifies.
478
479 Arguments:
480 This - Protocol instance pointer.
481
482
483 Returns:
484 EFI_SUCCESS - Reset the SCSI controller successfully.
485 EFI_DEVICE_ERROR - Errors are encountered when resetting the
486 SCSI Controller.
487 EFI_UNSUPPORTED - The SCSI bus does not support a device
488 reset operation.
489 EFI_TIMEOUT - A timeout occurred while attempting to
490 reset the SCSI Controller.
491 --*/
492 {
493 SCSI_IO_DEV *ScsiIoDevice;
494
495 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
496
497 return ScsiIoDevice->ScsiPassThru->ResetTarget (
498 ScsiIoDevice->ScsiPassThru,
499 ScsiIoDevice->Pun,
500 ScsiIoDevice->Lun
501 );
502 }
503
504 EFI_STATUS
505 EFIAPI
506 ScsiExecuteSCSICommand (
507 IN EFI_SCSI_IO_PROTOCOL *This,
508 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
509 IN EFI_EVENT Event OPTIONAL
510 )
511 /*++
512
513 Routine Description:
514 Sends a SCSI Request Packet to the SCSI Controller for execution.
515
516 Arguments:
517 This - Protocol instance pointer.
518 Packet - The SCSI request packet to send to the SCSI
519 Controller specified by the device handle.
520 Event - If the SCSI bus where the SCSI device is attached
521 does not support non-blocking I/O, then Event is
522 ignored, and blocking I/O is performed.
523 If Event is NULL, then blocking I/O is performed.
524 If Event is not NULL and non-blocking I/O is
525 supported, then non-blocking I/O is performed,
526 and Event will be signaled when the SCSI Request
527 Packet completes.
528 Returns:
529 EFI_SUCCESS - The SCSI Request Packet was sent by the host
530 successfully, and TransferLength bytes were
531 transferred to/from DataBuffer.See
532 HostAdapterStatus, TargetStatus,
533 SenseDataLength, and SenseData in that order
534 for additional status information.
535 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
536 but the entire DataBuffer could not be transferred.
537 The actual number of bytes transferred is returned
538 in TransferLength. See HostAdapterStatus,
539 TargetStatus, SenseDataLength, and SenseData in
540 that order for additional status information.
541 EFI_NOT_READY - The SCSI Request Packet could not be sent because
542 there are too many SCSI Command Packets already
543 queued.The caller may retry again later.
544 EFI_DEVICE_ERROR - A device error occurred while attempting to send
545 the SCSI Request Packet. See HostAdapterStatus,
546 TargetStatus, SenseDataLength, and SenseData in
547 that order for additional status information.
548 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
549 The SCSI Request Packet was not sent, so no
550 additional status information is available.
551 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
552 is not supported by the SCSI initiator(i.e., SCSI
553 Host Controller). The SCSI Request Packet was not
554 sent, so no additional status information is
555 available.
556 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
557 Request Packet to execute. See HostAdapterStatus,
558 TargetStatus, SenseDataLength, and SenseData in
559 that order for additional status information.
560 --*/
561 {
562 SCSI_IO_DEV *ScsiIoDevice;
563 EFI_STATUS Status;
564
565 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *RequestPacket;
566
567 if (Packet == NULL) {
568 return EFI_INVALID_PARAMETER;
569 }
570
571 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
572
573 RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;
574
575 Status = ScsiIoDevice->ScsiPassThru->PassThru (
576 ScsiIoDevice->ScsiPassThru,
577 ScsiIoDevice->Pun,
578 ScsiIoDevice->Lun,
579 RequestPacket,
580 Event
581 );
582 return Status;
583 }
584
585 EFI_STATUS
586 ScsiScanCreateDevice (
587 EFI_DRIVER_BINDING_PROTOCOL *This,
588 EFI_HANDLE Controller,
589 UINT32 Pun,
590 UINT64 Lun,
591 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru,
592 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath
593 )
594 /*++
595
596 Routine Description:
597
598 TODO: Add function description
599
600 Arguments:
601
602 This - TODO: add argument description
603 Controller - TODO: add argument description
604 Pun - TODO: add argument description
605 Lun - TODO: add argument description
606 ScsiPassThru - TODO: add argument description
607 ParentDevicePath - TODO: add argument description
608
609 Returns:
610
611 EFI_SUCCESS - TODO: Add description for return value
612 EFI_OUT_OF_RESOURCES - TODO: Add description for return value
613 EFI_SUCCESS - TODO: Add description for return value
614
615 --*/
616 {
617 EFI_STATUS Status;
618 SCSI_IO_DEV *ScsiIoDevice;
619 EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
620
621 Status = gBS->AllocatePool (
622 EfiBootServicesData,
623 sizeof (SCSI_IO_DEV),
624 (VOID **) &ScsiIoDevice
625 );
626 if (EFI_ERROR (Status)) {
627 return Status;
628 }
629
630 ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));
631
632 ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
633 ScsiIoDevice->ScsiPassThru = ScsiPassThru;
634 ScsiIoDevice->Pun = Pun;
635 ScsiIoDevice->Lun = Lun;
636
637 ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;
638 // ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;
639 ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;
640 ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
641 ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
642
643 if (!DiscoverScsiDevice (ScsiIoDevice)) {
644 gBS->FreePool (ScsiIoDevice);
645 return EFI_SUCCESS;
646 }
647
648 //
649 // Set Device Path
650 //
651 Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
652 ScsiIoDevice->ScsiPassThru,
653 ScsiIoDevice->Pun,
654 ScsiIoDevice->Lun,
655 &ScsiDevicePath
656 );
657 if (Status == EFI_OUT_OF_RESOURCES) {
658 gBS->FreePool (ScsiIoDevice);
659 return Status;
660 }
661
662 ScsiIoDevice->DevicePath = AppendDevicePathNode (
663 ParentDevicePath,
664 ScsiDevicePath
665 );
666 //
667 // The memory space for ScsiDevicePath is allocated in
668 // ScsiPassThru->BuildDevicePath() function; It is no longer used
669 // after EfiAppendDevicePathNode,so free the memory it occupies.
670 //
671 gBS->FreePool (ScsiDevicePath);
672
673 if (ScsiIoDevice->DevicePath == NULL) {
674 gBS->FreePool (ScsiIoDevice);
675 return EFI_OUT_OF_RESOURCES;
676 }
677
678 Status = gBS->InstallMultipleProtocolInterfaces (
679 &ScsiIoDevice->Handle,
680 &gEfiDevicePathProtocolGuid,
681 ScsiIoDevice->DevicePath,
682 &gEfiScsiIoProtocolGuid,
683 &ScsiIoDevice->ScsiIo,
684 NULL
685 );
686 if (EFI_ERROR (Status)) {
687 gBS->FreePool (ScsiIoDevice);
688 } else {
689 gBS->OpenProtocol (
690 Controller,
691 &gEfiScsiPassThruProtocolGuid,
692 (VOID **) &ScsiPassThru,
693 This->DriverBindingHandle,
694 ScsiIoDevice->Handle,
695 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
696 );
697 }
698
699 return EFI_SUCCESS;
700 }
701
702 BOOLEAN
703 DiscoverScsiDevice (
704 SCSI_IO_DEV *ScsiIoDevice
705 )
706 /*++
707
708 Routine Description:
709
710 TODO: Add function description
711
712 Arguments:
713
714 ScsiIoDevice - TODO: add argument description
715
716 Returns:
717
718 TODO: add return values
719
720 --*/
721 {
722 EFI_STATUS Status;
723 EFI_SCSI_INQUIRY_DATA InquiryData;
724 UINT32 InquiryDataLength;
725 EFI_SCSI_SENSE_DATA SenseData;
726 UINT8 SenseDataLength;
727 UINT8 HostAdapterStatus;
728 UINT8 TargetStatus;
729
730 HostAdapterStatus = 0;
731 TargetStatus = 0;
732 //
733 // Using Inquiry command to scan for the device
734 //
735 InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
736 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
737
738 Status = SubmitInquiryCommand (
739 &ScsiIoDevice->ScsiIo,
740 EfiScsiStallSeconds (1),
741 (VOID *) &SenseData,
742 &SenseDataLength,
743 &HostAdapterStatus,
744 &TargetStatus,
745 (VOID *) &InquiryData,
746 &InquiryDataLength,
747 FALSE
748 );
749 if (EFI_ERROR (Status)) {
750 //
751 // ParseSenseData (&SenseData,SenseDataLength);
752 //
753 return FALSE;
754 }
755 //
756 // Retrieved inquiry data successfully
757 //
758 if ((InquiryData.Peripheral_Qualifier != 0) &&
759 (InquiryData.Peripheral_Qualifier != 3)) {
760 return FALSE;
761 }
762
763 if (InquiryData.Peripheral_Qualifier == 3) {
764 if (InquiryData.Peripheral_Type != 0x1f) {
765 return FALSE;
766 }
767 }
768
769 if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) {
770 return FALSE;
771 }
772
773 //
774 // valid device type and peripheral qualifier combination.
775 //
776 ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;
777 ScsiIoDevice->RemovableDevice = InquiryData.RMB;
778 if (InquiryData.Version == 0) {
779 ScsiIoDevice->ScsiVersion = 0;
780 } else {
781 //
782 // ANSI-approved version
783 //
784 ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);
785 }
786
787 return TRUE;
788 }