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