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