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