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