]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
CommitLineData
3b2dbece 1/** @file\r
2 SCSI Bus driver that layers on every SCSI Pass Thru and\r
3 Extended SCSI Pass Thru protocol in the system.\r
3a10d471 4\r
1ff7ed2c 5Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
eae9e51d
S
6Copyright (c) 1985 - 2022, American Megatrends International LLC.<BR>\r
7\r
9d510e61 8SPDX-License-Identifier: BSD-2-Clause-Patent\r
3a10d471 9\r
3b2dbece 10**/\r
3a10d471 11\r
3a10d471 12#include "ScsiBus.h"\r
13\r
1436aea4 14EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {\r
3a10d471 15 SCSIBusDriverBindingSupported,\r
16 SCSIBusDriverBindingStart,\r
17 SCSIBusDriverBindingStop,\r
18 0xa,\r
19 NULL,\r
20 NULL\r
21};\r
22\r
9beb888e 23VOID *mWorkingBuffer;\r
24\r
25/**\r
26 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.\r
70c94b3b 27\r
9beb888e 28 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
29 @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
30\r
31**/\r
70c94b3b 32EFI_STATUS\r
33EFIAPI\r
34ScsiioToPassThruPacket (\r
35 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,\r
9beb888e 36 OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket\r
ed66e1bc 37 );\r
70c94b3b 38\r
9beb888e 39/**\r
40 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.\r
41\r
42 @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
43 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
70c94b3b 44\r
9beb888e 45**/\r
70c94b3b 46EFI_STATUS\r
47EFIAPI\r
48PassThruToScsiioPacket (\r
49 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,\r
9beb888e 50 OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet\r
ed66e1bc 51 );\r
9beb888e 52\r
53/**\r
54 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0\r
55 SCSI IO Packet.\r
56\r
57 @param Event The instance of EFI_EVENT.\r
58 @param Context The parameter passed in.\r
59\r
60**/\r
70c94b3b 61VOID\r
62EFIAPI\r
63NotifyFunction (\r
9beb888e 64 IN EFI_EVENT Event,\r
65 IN VOID *Context\r
ed66e1bc 66 );\r
70c94b3b 67\r
957fe093
SZ
68/**\r
69 Allocates an aligned buffer for SCSI device.\r
70\r
71 This function allocates an aligned buffer for the SCSI device to perform\r
72 SCSI pass through operations. The alignment requirement is from SCSI pass\r
73 through interface.\r
74\r
75 @param ScsiIoDevice The SCSI child device involved for the operation.\r
76 @param BufferSize The request buffer size.\r
77\r
78 @return A pointer to the aligned buffer or NULL if the allocation fails.\r
79\r
80**/\r
81VOID *\r
82AllocateAlignedBuffer (\r
1436aea4
MK
83 IN SCSI_IO_DEV *ScsiIoDevice,\r
84 IN UINTN BufferSize\r
957fe093
SZ
85 )\r
86{\r
87 return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), ScsiIoDevice->ScsiIo.IoAlign);\r
88}\r
89\r
90/**\r
91 Frees an aligned buffer for SCSI device.\r
92\r
93 This function frees an aligned buffer for the SCSI device to perform\r
94 SCSI pass through operations.\r
95\r
96 @param Buffer The aligned buffer to be freed.\r
97 @param BufferSize The request buffer size.\r
98\r
99**/\r
100VOID\r
101FreeAlignedBuffer (\r
1436aea4
MK
102 IN VOID *Buffer,\r
103 IN UINTN BufferSize\r
957fe093
SZ
104 )\r
105{\r
106 if (Buffer != NULL) {\r
107 FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));\r
108 }\r
109}\r
110\r
3a10d471 111/**\r
112 The user Entry Point for module ScsiBus. The user code starts with this function.\r
113\r
9beb888e 114 @param ImageHandle The firmware allocated handle for the EFI image.\r
115 @param SystemTable A pointer to the EFI System Table.\r
c52fa98c 116\r
9beb888e 117 @retval EFI_SUCCESS The entry point is executed successfully.\r
118 @retval other Some error occurs when executing this entry point.\r
3a10d471 119\r
120**/\r
121EFI_STATUS\r
122EFIAPI\r
1436aea4
MK
123InitializeScsiBus (\r
124 IN EFI_HANDLE ImageHandle,\r
125 IN EFI_SYSTEM_TABLE *SystemTable\r
3a10d471 126 )\r
127{\r
1436aea4 128 EFI_STATUS Status;\r
3a10d471 129\r
130 //\r
131 // Install driver model protocol(s).\r
132 //\r
70da5bc2 133 Status = EfiLibInstallDriverBindingComponentName2 (\r
3a10d471 134 ImageHandle,\r
135 SystemTable,\r
136 &gSCSIBusDriverBinding,\r
137 ImageHandle,\r
138 &gScsiBusComponentName,\r
70da5bc2 139 &gScsiBusComponentName2\r
3a10d471 140 );\r
141 ASSERT_EFI_ERROR (Status);\r
142\r
3a10d471 143 return Status;\r
144}\r
145\r
9beb888e 146/**\r
147 Test to see if this driver supports ControllerHandle.\r
148\r
149 This service is called by the EFI boot service ConnectController(). In order\r
150 to make drivers as small as possible, there are a few calling restrictions for\r
151 this service. ConnectController() must follow these calling restrictions. If\r
152 any other agent wishes to call Supported() it must also follow these calling\r
153 restrictions.\r
154\r
155 @param This Protocol instance pointer.\r
156 @param ControllerHandle Handle of device to test\r
157 @param RemainingDevicePath Optional parameter use to pick a specific child\r
158 device to start.\r
159\r
160 @retval EFI_SUCCESS This driver supports this device\r
161 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
162 @retval other This driver does not support this device\r
163\r
164**/\r
3a10d471 165EFI_STATUS\r
166EFIAPI\r
167SCSIBusDriverBindingSupported (\r
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
169 IN EFI_HANDLE Controller,\r
170 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
171 )\r
3a10d471 172{\r
1436aea4
MK
173 EFI_STATUS Status;\r
174 EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
175 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\r
176 UINT64 Lun;\r
177 UINT8 *TargetId;\r
178 SCSI_TARGET_ID ScsiTargetId;\r
af4a6385 179\r
d548f0a1 180 TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];\r
181 SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
182\r
183 //\r
d1102dba 184 // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as\r
d548f0a1 185 // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly\r
186 // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.\r
187 //\r
188 Status = gBS->OpenProtocol (\r
189 Controller,\r
190 &gEfiExtScsiPassThruProtocolGuid,\r
191 (VOID **)&ExtPassThru,\r
192 This->DriverBindingHandle,\r
193 Controller,\r
194 EFI_OPEN_PROTOCOL_BY_DRIVER\r
195 );\r
196\r
197 if (Status == EFI_ALREADY_STARTED) {\r
198 return EFI_SUCCESS;\r
1436aea4 199 } else if (!EFI_ERROR (Status)) {\r
af4a6385 200 //\r
d548f0a1 201 // Check if RemainingDevicePath is NULL or the End of Device Path Node,\r
202 // if yes, return EFI_SUCCESS.\r
af4a6385 203 //\r
d548f0a1 204 if ((RemainingDevicePath == NULL) || IsDevicePathEnd (RemainingDevicePath)) {\r
67f7e376 205 //\r
206 // Close protocol regardless of RemainingDevicePath validation\r
207 //\r
208 gBS->CloseProtocol (\r
209 Controller,\r
210 &gEfiExtScsiPassThruProtocolGuid,\r
211 This->DriverBindingHandle,\r
212 Controller\r
d1102dba 213 );\r
d548f0a1 214 return EFI_SUCCESS;\r
215 } else {\r
216 //\r
217 // If RemainingDevicePath isn't the End of Device Path Node, check its validation\r
218 //\r
219 Status = ExtPassThru->GetTargetLun (ExtPassThru, RemainingDevicePath, &TargetId, &Lun);\r
af4a6385 220 //\r
d548f0a1 221 // Close protocol regardless of RemainingDevicePath validation\r
af4a6385 222 //\r
d548f0a1 223 gBS->CloseProtocol (\r
224 Controller,\r
225 &gEfiExtScsiPassThruProtocolGuid,\r
226 This->DriverBindingHandle,\r
227 Controller\r
d1102dba 228 );\r
1436aea4 229 if (!EFI_ERROR (Status)) {\r
d548f0a1 230 return EFI_SUCCESS;\r
af4a6385 231 }\r
232 }\r
233 }\r
234\r
3a10d471 235 //\r
d1102dba 236 // Come here in 2 condition:\r
d548f0a1 237 // 1. ExtPassThru doesn't exist.\r
238 // 2. ExtPassThru exists but RemainingDevicePath is invalid.\r
3a10d471 239 //\r
240 Status = gBS->OpenProtocol (\r
241 Controller,\r
d548f0a1 242 &gEfiScsiPassThruProtocolGuid,\r
243 (VOID **)&PassThru,\r
3a10d471 244 This->DriverBindingHandle,\r
245 Controller,\r
70c94b3b 246 EFI_OPEN_PROTOCOL_BY_DRIVER\r
3a10d471 247 );\r
d1102dba 248\r
70c94b3b 249 if (Status == EFI_ALREADY_STARTED) {\r
250 return EFI_SUCCESS;\r
251 }\r
d1102dba 252\r
70c94b3b 253 if (EFI_ERROR (Status)) {\r
d548f0a1 254 return Status;\r
3a10d471 255 }\r
d1102dba 256\r
af4a6385 257 //\r
d548f0a1 258 // Test RemainingDevicePath is valid or not.\r
af4a6385 259 //\r
d548f0a1 260 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
261 Status = PassThru->GetTargetLun (PassThru, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
262 }\r
d1102dba 263\r
70c94b3b 264 gBS->CloseProtocol (\r
d548f0a1 265 Controller,\r
266 &gEfiScsiPassThruProtocolGuid,\r
267 This->DriverBindingHandle,\r
268 Controller\r
269 );\r
270 return Status;\r
3a10d471 271}\r
272\r
9beb888e 273/**\r
274 Start this driver on ControllerHandle.\r
275\r
276 This service is called by the EFI boot service ConnectController(). In order\r
277 to make drivers as small as possible, there are a few calling restrictions for\r
278 this service. ConnectController() must follow these calling restrictions. If\r
279 any other agent wishes to call Start() it must also follow these calling\r
280 restrictions.\r
281\r
282 @param This Protocol instance pointer.\r
283 @param ControllerHandle Handle of device to bind driver to\r
284 @param RemainingDevicePath Optional parameter use to pick a specific child\r
285 device to start.\r
286\r
287 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
288 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
289 @retval other This driver does not support this device\r
290\r
291**/\r
3a10d471 292EFI_STATUS\r
293EFIAPI\r
294SCSIBusDriverBindingStart (\r
295 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
296 IN EFI_HANDLE Controller,\r
297 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
298 )\r
3a10d471 299{\r
1436aea4
MK
300 UINT64 Lun;\r
301 UINT8 *TargetId;\r
302 BOOLEAN ScanOtherPuns;\r
303 BOOLEAN FromFirstTarget;\r
304 BOOLEAN ExtScsiSupport;\r
305 EFI_STATUS Status;\r
306 EFI_STATUS DevicePathStatus;\r
307 EFI_STATUS PassThruStatus;\r
308 SCSI_BUS_DEVICE *ScsiBusDev;\r
309 SCSI_TARGET_ID ScsiTargetId;\r
310 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
311 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;\r
312 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;\r
313 EFI_SCSI_BUS_PROTOCOL *BusIdentify;\r
f36d6e66 314\r
315 TargetId = NULL;\r
f36d6e66 316 ScanOtherPuns = TRUE;\r
70c94b3b 317 FromFirstTarget = FALSE;\r
f36d6e66 318 ExtScsiSupport = FALSE;\r
319 PassThruStatus = EFI_SUCCESS;\r
d1102dba 320\r
d548f0a1 321 TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];\r
322 SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
d1102dba 323\r
f36d6e66 324 DevicePathStatus = gBS->OpenProtocol (\r
325 Controller,\r
326 &gEfiDevicePathProtocolGuid,\r
1436aea4 327 (VOID **)&ParentDevicePath,\r
f36d6e66 328 This->DriverBindingHandle,\r
329 Controller,\r
330 EFI_OPEN_PROTOCOL_BY_DRIVER\r
331 );\r
332 if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {\r
333 return DevicePathStatus;\r
3a10d471 334 }\r
335\r
37623a5c 336 //\r
337 // Report Status Code to indicate SCSI bus starts\r
338 //\r
339 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
340 EFI_PROGRESS_CODE,\r
341 (EFI_IO_BUS_SCSI | EFI_IOB_PC_INIT),\r
342 ParentDevicePath\r
d1102dba 343 );\r
37623a5c 344\r
3a10d471 345 //\r
d1102dba 346 // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as\r
f36d6e66 347 // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly\r
348 // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.\r
3a10d471 349 //\r
350 Status = gBS->OpenProtocol (\r
351 Controller,\r
70c94b3b 352 &gEfiExtScsiPassThruProtocolGuid,\r
1436aea4 353 (VOID **)&ExtScsiInterface,\r
3a10d471 354 This->DriverBindingHandle,\r
355 Controller,\r
356 EFI_OPEN_PROTOCOL_BY_DRIVER\r
357 );\r
f36d6e66 358 //\r
359 // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.\r
360 //\r
1436aea4 361 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
70c94b3b 362 Status = gBS->OpenProtocol (\r
363 Controller,\r
364 &gEfiScsiPassThruProtocolGuid,\r
1436aea4 365 (VOID **)&ScsiInterface,\r
70c94b3b 366 This->DriverBindingHandle,\r
367 Controller,\r
368 EFI_OPEN_PROTOCOL_BY_DRIVER\r
369 );\r
f36d6e66 370 //\r
371 // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.\r
372 //\r
373 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
1436aea4 374 if (!EFI_ERROR (DevicePathStatus)) {\r
f36d6e66 375 gBS->CloseProtocol (\r
376 Controller,\r
377 &gEfiDevicePathProtocolGuid,\r
378 This->DriverBindingHandle,\r
379 Controller\r
380 );\r
d1102dba 381 }\r
1436aea4 382\r
70c94b3b 383 return Status;\r
d1102dba 384 }\r
70c94b3b 385 } else {\r
f36d6e66 386 //\r
d1102dba
LG
387 // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol\r
388 // with BY_DRIVER if it is also present on the handle. The intent is to prevent\r
f36d6e66 389 // another SCSI Bus Driver to work on the same host handle.\r
390 //\r
391 ExtScsiSupport = TRUE;\r
392 PassThruStatus = gBS->OpenProtocol (\r
393 Controller,\r
394 &gEfiScsiPassThruProtocolGuid,\r
1436aea4 395 (VOID **)&ScsiInterface,\r
f36d6e66 396 This->DriverBindingHandle,\r
397 Controller,\r
398 EFI_OPEN_PROTOCOL_BY_DRIVER\r
399 );\r
70c94b3b 400 }\r
d1102dba 401\r
f36d6e66 402 if (Status != EFI_ALREADY_STARTED) {\r
403 //\r
404 // Go through here means either ExtPassThru or PassThru Protocol is successfully opened\r
405 // on this handle for this time. Then construct Host controller private data.\r
406 //\r
407 ScsiBusDev = NULL;\r
1436aea4 408 ScsiBusDev = AllocateZeroPool (sizeof (SCSI_BUS_DEVICE));\r
f36d6e66 409 if (ScsiBusDev == NULL) {\r
410 Status = EFI_OUT_OF_RESOURCES;\r
411 goto ErrorExit;\r
412 }\r
1436aea4
MK
413\r
414 ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;\r
415 ScsiBusDev->ExtScsiSupport = ExtScsiSupport;\r
416 ScsiBusDev->DevicePath = ParentDevicePath;\r
70c94b3b 417 if (ScsiBusDev->ExtScsiSupport) {\r
f36d6e66 418 ScsiBusDev->ExtScsiInterface = ExtScsiInterface;\r
70c94b3b 419 } else {\r
1436aea4 420 ScsiBusDev->ScsiInterface = ScsiInterface;\r
70c94b3b 421 }\r
f36d6e66 422\r
423 //\r
424 // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be\r
425 // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru\r
426 // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.\r
d1102dba 427 //\r
f36d6e66 428 Status = gBS->InstallProtocolInterface (\r
429 &Controller,\r
c8ad2d7a 430 &gEfiCallerIdGuid,\r
f36d6e66 431 EFI_NATIVE_INTERFACE,\r
432 &ScsiBusDev->BusIdentify\r
433 );\r
434 if (EFI_ERROR (Status)) {\r
435 goto ErrorExit;\r
436 }\r
437 } else {\r
438 //\r
439 // Go through here means Start() is re-invoked again, nothing special is required to do except\r
440 // picking up Host controller private information.\r
441 //\r
442 Status = gBS->OpenProtocol (\r
443 Controller,\r
c8ad2d7a 444 &gEfiCallerIdGuid,\r
1436aea4 445 (VOID **)&BusIdentify,\r
f36d6e66 446 This->DriverBindingHandle,\r
447 Controller,\r
448 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
449 );\r
450\r
451 if (EFI_ERROR (Status)) {\r
452 return Status;\r
453 }\r
1436aea4 454\r
f36d6e66 455 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);\r
3a10d471 456 }\r
457\r
37623a5c 458 //\r
459 // Report Status Code to indicate detecting devices on bus\r
460 //\r
461 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
462 EFI_PROGRESS_CODE,\r
463 (EFI_IO_BUS_SCSI | EFI_IOB_PC_DETECT),\r
464 ParentDevicePath\r
465 );\r
466\r
1436aea4 467 Lun = 0;\r
3a10d471 468 if (RemainingDevicePath == NULL) {\r
af4a6385 469 //\r
d1102dba 470 // If RemainingDevicePath is NULL,\r
af4a6385 471 // must enumerate all SCSI devices anyway\r
472 //\r
70c94b3b 473 FromFirstTarget = TRUE;\r
af4a6385 474 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
475 //\r
d1102dba 476 // If RemainingDevicePath isn't the End of Device Path Node,\r
af4a6385 477 // only scan the specified device by RemainingDevicePath\r
478 //\r
70c94b3b 479 if (ScsiBusDev->ExtScsiSupport) {\r
d1102dba 480 Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);\r
70c94b3b 481 } else {\r
d10a41e6 482 Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
70c94b3b 483 }\r
af4a6385 484\r
d10a41e6 485 if (EFI_ERROR (Status)) {\r
486 return Status;\r
487 }\r
af4a6385 488 } else {\r
489 //\r
490 // If RemainingDevicePath is the End of Device Path Node,\r
cc530cd1 491 // skip enumerate any device and return EFI_SUCCESS\r
d1102dba 492 //\r
af4a6385 493 ScanOtherPuns = FALSE;\r
3a10d471 494 }\r
495\r
1436aea4 496 while (ScanOtherPuns) {\r
70c94b3b 497 if (FromFirstTarget) {\r
3a10d471 498 //\r
499 // Remaining Device Path is NULL, scan all the possible Puns in the\r
500 // SCSI Channel.\r
501 //\r
70c94b3b 502 if (ScsiBusDev->ExtScsiSupport) {\r
503 Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);\r
504 } else {\r
d548f0a1 505 Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
70c94b3b 506 }\r
1436aea4 507\r
3a10d471 508 if (EFI_ERROR (Status)) {\r
509 //\r
510 // no legal Pun and Lun found any more\r
511 //\r
512 break;\r
513 }\r
514 } else {\r
3a10d471 515 ScanOtherPuns = FALSE;\r
516 }\r
1436aea4 517\r
3a10d471 518 //\r
519 // Avoid creating handle for the host adapter.\r
520 //\r
70c94b3b 521 if (ScsiBusDev->ExtScsiSupport) {\r
d548f0a1 522 if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {\r
70c94b3b 523 continue;\r
524 }\r
525 } else {\r
d548f0a1 526 if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {\r
70c94b3b 527 continue;\r
528 }\r
3a10d471 529 }\r
1436aea4 530\r
3a10d471 531 //\r
532 // Scan for the scsi device, if it attaches to the scsi bus,\r
533 // then create handle and install scsi i/o protocol.\r
534 //\r
d548f0a1 535 Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev);\r
eae9e51d
S
536 if (Status == EFI_OUT_OF_RESOURCES) {\r
537 goto ErrorExit;\r
538 }\r
3a10d471 539 }\r
1436aea4 540\r
f36d6e66 541 return EFI_SUCCESS;\r
9b38ff34 542\r
f36d6e66 543ErrorExit:\r
d1102dba 544\r
f36d6e66 545 if (ScsiBusDev != NULL) {\r
9b38ff34 546 FreePool (ScsiBusDev);\r
f36d6e66 547 }\r
d1102dba 548\r
f36d6e66 549 if (ExtScsiSupport) {\r
550 gBS->CloseProtocol (\r
551 Controller,\r
552 &gEfiExtScsiPassThruProtocolGuid,\r
553 This->DriverBindingHandle,\r
554 Controller\r
555 );\r
556 if (!EFI_ERROR (PassThruStatus)) {\r
557 gBS->CloseProtocol (\r
558 Controller,\r
559 &gEfiScsiPassThruProtocolGuid,\r
560 This->DriverBindingHandle,\r
561 Controller\r
562 );\r
563 }\r
564 } else {\r
565 gBS->CloseProtocol (\r
566 Controller,\r
567 &gEfiScsiPassThruProtocolGuid,\r
568 This->DriverBindingHandle,\r
569 Controller\r
570 );\r
571 }\r
1436aea4 572\r
3a10d471 573 return Status;\r
574}\r
575\r
9beb888e 576/**\r
577 Stop this driver on ControllerHandle.\r
578\r
579 This service is called by the EFI boot service DisconnectController().\r
580 In order to make drivers as small as possible, there are a few calling\r
581 restrictions for this service. DisconnectController() must follow these\r
582 calling restrictions. If any other agent wishes to call Stop() it must also\r
583 follow these calling restrictions.\r
d1102dba 584\r
9beb888e 585 @param This Protocol instance pointer.\r
586 @param ControllerHandle Handle of device to stop driver on\r
587 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
588 children is zero stop the entire bus driver.\r
589 @param ChildHandleBuffer List of Child Handles to Stop.\r
590\r
591 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
592 @retval other This driver was not removed from this device\r
593\r
594**/\r
3a10d471 595EFI_STATUS\r
596EFIAPI\r
597SCSIBusDriverBindingStop (\r
1436aea4
MK
598 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
599 IN EFI_HANDLE Controller,\r
600 IN UINTN NumberOfChildren,\r
601 IN EFI_HANDLE *ChildHandleBuffer\r
3a10d471 602 )\r
3a10d471 603{\r
1436aea4
MK
604 EFI_STATUS Status;\r
605 BOOLEAN AllChildrenStopped;\r
606 UINTN Index;\r
607 EFI_SCSI_IO_PROTOCOL *ScsiIo;\r
608 SCSI_IO_DEV *ScsiIoDevice;\r
609 VOID *ScsiPassThru;\r
610 EFI_SCSI_BUS_PROTOCOL *Scsidentifier;\r
611 SCSI_BUS_DEVICE *ScsiBusDev;\r
3a10d471 612\r
613 if (NumberOfChildren == 0) {\r
70c94b3b 614 //\r
615 // Get the SCSI_BUS_DEVICE\r
616 //\r
617 Status = gBS->OpenProtocol (\r
618 Controller,\r
c8ad2d7a 619 &gEfiCallerIdGuid,\r
1436aea4 620 (VOID **)&Scsidentifier,\r
70c94b3b 621 This->DriverBindingHandle,\r
622 Controller,\r
623 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
624 );\r
c52fa98c 625\r
70c94b3b 626 if (EFI_ERROR (Status)) {\r
627 return EFI_DEVICE_ERROR;\r
628 }\r
629\r
630 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier);\r
631\r
632 //\r
633 // Uninstall SCSI Bus Protocol\r
634 //\r
635 gBS->UninstallProtocolInterface (\r
636 Controller,\r
c8ad2d7a 637 &gEfiCallerIdGuid,\r
70c94b3b 638 &ScsiBusDev->BusIdentify\r
639 );\r
c52fa98c 640\r
3a10d471 641 //\r
642 // Close the bus driver\r
643 //\r
70c94b3b 644 if (ScsiBusDev->ExtScsiSupport) {\r
1e5914b5 645 //\r
646 // Close ExtPassThru Protocol from this controller handle\r
647 //\r
70c94b3b 648 gBS->CloseProtocol (\r
649 Controller,\r
650 &gEfiExtScsiPassThruProtocolGuid,\r
651 This->DriverBindingHandle,\r
652 Controller\r
653 );\r
1e5914b5 654 //\r
655 // When Start() succeeds to open ExtPassThru, it always tries to open PassThru BY_DRIVER.\r
cc530cd1 656 // Its intent is to prevent another SCSI Bus Driver from working on the same host handle.\r
1e5914b5 657 // So Stop() needs to try to close PassThru if present here.\r
658 //\r
659 gBS->CloseProtocol (\r
660 Controller,\r
661 &gEfiScsiPassThruProtocolGuid,\r
662 This->DriverBindingHandle,\r
663 Controller\r
664 );\r
70c94b3b 665 } else {\r
666 gBS->CloseProtocol (\r
667 Controller,\r
668 &gEfiScsiPassThruProtocolGuid,\r
669 This->DriverBindingHandle,\r
670 Controller\r
671 );\r
672 }\r
3a10d471 673\r
70c94b3b 674 gBS->CloseProtocol (\r
675 Controller,\r
676 &gEfiDevicePathProtocolGuid,\r
677 This->DriverBindingHandle,\r
678 Controller\r
679 );\r
6c94a00d 680 FreePool (ScsiBusDev);\r
3a10d471 681 return EFI_SUCCESS;\r
682 }\r
683\r
684 AllChildrenStopped = TRUE;\r
685\r
686 for (Index = 0; Index < NumberOfChildren; Index++) {\r
3a10d471 687 Status = gBS->OpenProtocol (\r
688 ChildHandleBuffer[Index],\r
689 &gEfiScsiIoProtocolGuid,\r
1436aea4 690 (VOID **)&ScsiIo,\r
3a10d471 691 This->DriverBindingHandle,\r
692 Controller,\r
693 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
694 );\r
695 if (EFI_ERROR (Status)) {\r
696 AllChildrenStopped = FALSE;\r
697 continue;\r
698 }\r
699\r
700 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);\r
701 //\r
702 // Close the child handle\r
703 //\r
70c94b3b 704 if (ScsiIoDevice->ExtScsiSupport) {\r
705 Status = gBS->CloseProtocol (\r
706 Controller,\r
707 &gEfiExtScsiPassThruProtocolGuid,\r
708 This->DriverBindingHandle,\r
709 ChildHandleBuffer[Index]\r
710 );\r
70c94b3b 711 } else {\r
712 Status = gBS->CloseProtocol (\r
713 Controller,\r
714 &gEfiScsiPassThruProtocolGuid,\r
715 This->DriverBindingHandle,\r
716 ChildHandleBuffer[Index]\r
717 );\r
718 }\r
3a10d471 719\r
720 Status = gBS->UninstallMultipleProtocolInterfaces (\r
721 ChildHandleBuffer[Index],\r
722 &gEfiDevicePathProtocolGuid,\r
723 ScsiIoDevice->DevicePath,\r
724 &gEfiScsiIoProtocolGuid,\r
725 &ScsiIoDevice->ScsiIo,\r
726 NULL\r
727 );\r
728 if (EFI_ERROR (Status)) {\r
729 AllChildrenStopped = FALSE;\r
70c94b3b 730 if (ScsiIoDevice->ExtScsiSupport) {\r
731 gBS->OpenProtocol (\r
732 Controller,\r
733 &gEfiExtScsiPassThruProtocolGuid,\r
84b5c78e 734 &ScsiPassThru,\r
70c94b3b 735 This->DriverBindingHandle,\r
736 ChildHandleBuffer[Index],\r
737 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
738 );\r
739 } else {\r
740 gBS->OpenProtocol (\r
741 Controller,\r
742 &gEfiScsiPassThruProtocolGuid,\r
84b5c78e 743 &ScsiPassThru,\r
70c94b3b 744 This->DriverBindingHandle,\r
745 ChildHandleBuffer[Index],\r
746 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
747 );\r
748 }\r
3a10d471 749 } else {\r
6c94a00d 750 FreePool (ScsiIoDevice);\r
3a10d471 751 }\r
752 }\r
753\r
754 if (!AllChildrenStopped) {\r
755 return EFI_DEVICE_ERROR;\r
756 }\r
757\r
758 return EFI_SUCCESS;\r
759}\r
760\r
9beb888e 761/**\r
762 Retrieves the device type information of the SCSI Controller.\r
763\r
764 @param This Protocol instance pointer.\r
765 @param DeviceType A pointer to the device type information retrieved from\r
d1102dba 766 the SCSI Controller.\r
9beb888e 767\r
768 @retval EFI_SUCCESS Retrieves the device type information successfully.\r
769 @retval EFI_INVALID_PARAMETER The DeviceType is NULL.\r
d1102dba 770\r
9beb888e 771**/\r
3a10d471 772EFI_STATUS\r
773EFIAPI\r
774ScsiGetDeviceType (\r
1436aea4
MK
775 IN EFI_SCSI_IO_PROTOCOL *This,\r
776 OUT UINT8 *DeviceType\r
3a10d471 777 )\r
3a10d471 778{\r
1436aea4 779 SCSI_IO_DEV *ScsiIoDevice;\r
3a10d471 780\r
781 if (DeviceType == NULL) {\r
782 return EFI_INVALID_PARAMETER;\r
783 }\r
784\r
1436aea4
MK
785 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
786 *DeviceType = ScsiIoDevice->ScsiDeviceType;\r
3a10d471 787 return EFI_SUCCESS;\r
788}\r
789\r
9beb888e 790/**\r
791 Retrieves the device location in the SCSI channel.\r
792\r
793 @param This Protocol instance pointer.\r
794 @param Target A pointer to the Target ID of a SCSI device\r
795 on the SCSI channel.\r
796 @param Lun A pointer to the LUN of the SCSI device on\r
797 the SCSI channel.\r
798\r
799 @retval EFI_SUCCESS Retrieves the device location successfully.\r
800 @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.\r
801\r
802**/\r
3a10d471 803EFI_STATUS\r
804EFIAPI\r
805ScsiGetDeviceLocation (\r
1436aea4
MK
806 IN EFI_SCSI_IO_PROTOCOL *This,\r
807 IN OUT UINT8 **Target,\r
808 OUT UINT64 *Lun\r
3a10d471 809 )\r
3a10d471 810{\r
1436aea4 811 SCSI_IO_DEV *ScsiIoDevice;\r
3a10d471 812\r
1436aea4 813 if ((Target == NULL) || (Lun == NULL)) {\r
3a10d471 814 return EFI_INVALID_PARAMETER;\r
815 }\r
816\r
f36d6e66 817 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
3a10d471 818\r
1436aea4 819 CopyMem (*Target, &ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
70c94b3b 820\r
1436aea4 821 *Lun = ScsiIoDevice->Lun;\r
3a10d471 822\r
823 return EFI_SUCCESS;\r
824}\r
825\r
9beb888e 826/**\r
827 Resets the SCSI Bus that the SCSI Controller is attached to.\r
828\r
829 @param This Protocol instance pointer.\r
830\r
831 @retval EFI_SUCCESS The SCSI bus is reset successfully.\r
832 @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus.\r
833 @retval EFI_UNSUPPORTED The bus reset operation is not supported by the\r
834 SCSI Host Controller.\r
d1102dba 835 @retval EFI_TIMEOUT A timeout occurred while attempting to reset\r
9beb888e 836 the SCSI bus.\r
837**/\r
3a10d471 838EFI_STATUS\r
839EFIAPI\r
840ScsiResetBus (\r
1436aea4 841 IN EFI_SCSI_IO_PROTOCOL *This\r
3a10d471 842 )\r
3a10d471 843{\r
1436aea4 844 SCSI_IO_DEV *ScsiIoDevice;\r
3a10d471 845\r
846 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
847\r
37623a5c 848 //\r
849 // Report Status Code to indicate reset happens\r
850 //\r
851 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
852 EFI_PROGRESS_CODE,\r
853 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
854 ScsiIoDevice->ScsiBusDeviceData->DevicePath\r
855 );\r
856\r
1436aea4 857 if (ScsiIoDevice->ExtScsiSupport) {\r
70c94b3b 858 return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru);\r
859 } else {\r
860 return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);\r
861 }\r
3a10d471 862}\r
863\r
9beb888e 864/**\r
865 Resets the SCSI Controller that the device handle specifies.\r
866\r
867 @param This Protocol instance pointer.\r
868\r
869 @retval EFI_SUCCESS Reset the SCSI controller successfully.\r
870 @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller.\r
871 @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation.\r
872 @retval EFI_TIMEOUT A timeout occurred while attempting to reset the\r
873 SCSI Controller.\r
874**/\r
3a10d471 875EFI_STATUS\r
876EFIAPI\r
877ScsiResetDevice (\r
1436aea4 878 IN EFI_SCSI_IO_PROTOCOL *This\r
3a10d471 879 )\r
3a10d471 880{\r
f36d6e66 881 SCSI_IO_DEV *ScsiIoDevice;\r
70c94b3b 882 UINT8 Target[TARGET_MAX_BYTES];\r
3a10d471 883\r
884 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
37623a5c 885\r
886 //\r
887 // Report Status Code to indicate reset happens\r
888 //\r
889 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
890 EFI_PROGRESS_CODE,\r
891 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
892 ScsiIoDevice->ScsiBusDeviceData->DevicePath\r
893 );\r
d1102dba 894\r
1436aea4 895 CopyMem (Target, &ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
3a10d471 896\r
70c94b3b 897 if (ScsiIoDevice->ExtScsiSupport) {\r
898 return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (\r
1436aea4
MK
899 ScsiIoDevice->ExtScsiPassThru,\r
900 Target,\r
901 ScsiIoDevice->Lun\r
902 );\r
70c94b3b 903 } else {\r
904 return ScsiIoDevice->ScsiPassThru->ResetTarget (\r
1436aea4
MK
905 ScsiIoDevice->ScsiPassThru,\r
906 ScsiIoDevice->Pun.ScsiId.Scsi,\r
907 ScsiIoDevice->Lun\r
908 );\r
70c94b3b 909 }\r
3a10d471 910}\r
911\r
9beb888e 912/**\r
f36d6e66 913 Sends a SCSI Request Packet to the SCSI Controller for execution.\r
f36d6e66 914\r
9beb888e 915 @param This Protocol instance pointer.\r
d1102dba 916 @param CommandPacket The SCSI request packet to send to the SCSI\r
f36d6e66 917 Controller specified by the device handle.\r
9beb888e 918 @param Event If the SCSI bus where the SCSI device is attached\r
d1102dba
LG
919 does not support non-blocking I/O, then Event is\r
920 ignored, and blocking I/O is performed.\r
f36d6e66 921 If Event is NULL, then blocking I/O is performed.\r
d1102dba 922 If Event is not NULL and non-blocking I/O is\r
f36d6e66 923 supported, then non-blocking I/O is performed,\r
924 and Event will be signaled when the SCSI Request\r
925 Packet completes.\r
9beb888e 926\r
d1102dba
LG
927 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host\r
928 successfully, and TransferLength bytes were\r
929 transferred to/from DataBuffer.See\r
930 HostAdapterStatus, TargetStatus,\r
9beb888e 931 SenseDataLength, and SenseData in that order\r
932 for additional status information.\r
d1102dba 933 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
9beb888e 934 but the entire DataBuffer could not be transferred.\r
935 The actual number of bytes transferred is returned\r
d1102dba
LG
936 in TransferLength. See HostAdapterStatus,\r
937 TargetStatus, SenseDataLength, and SenseData in\r
9beb888e 938 that order for additional status information.\r
d1102dba
LG
939 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
940 there are too many SCSI Command Packets already\r
9beb888e 941 queued.The caller may retry again later.\r
d1102dba
LG
942 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
943 the SCSI Request Packet. See HostAdapterStatus,\r
944 TargetStatus, SenseDataLength, and SenseData in\r
9beb888e 945 that order for additional status information.\r
d1102dba
LG
946 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.\r
947 The SCSI Request Packet was not sent, so no\r
9beb888e 948 additional status information is available.\r
949 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
d1102dba 950 is not supported by the SCSI initiator(i.e., SCSI\r
9beb888e 951 Host Controller). The SCSI Request Packet was not\r
d1102dba 952 sent, so no additional status information is\r
9beb888e 953 available.\r
d1102dba 954 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
9beb888e 955 Request Packet to execute. See HostAdapterStatus,\r
d1102dba 956 TargetStatus, SenseDataLength, and SenseData in\r
9beb888e 957 that order for additional status information.\r
958**/\r
959EFI_STATUS\r
960EFIAPI\r
961ScsiExecuteSCSICommand (\r
1436aea4
MK
962 IN EFI_SCSI_IO_PROTOCOL *This,\r
963 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,\r
964 IN EFI_EVENT Event OPTIONAL\r
9beb888e 965 )\r
3a10d471 966{\r
f36d6e66 967 SCSI_IO_DEV *ScsiIoDevice;\r
968 EFI_STATUS Status;\r
70c94b3b 969 UINT8 Target[TARGET_MAX_BYTES];\r
970 EFI_EVENT PacketEvent;\r
971 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;\r
d1102dba 972 SCSI_EVENT_DATA EventData;\r
3a10d471 973\r
70c94b3b 974 PacketEvent = NULL;\r
d1102dba 975\r
3a10d471 976 if (Packet == NULL) {\r
977 return EFI_INVALID_PARAMETER;\r
978 }\r
979\r
1436aea4
MK
980 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
981 CopyMem (Target, &ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
c52fa98c 982\r
70c94b3b 983 if (ScsiIoDevice->ExtScsiSupport) {\r
1436aea4 984 ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *)Packet;\r
0d12e6a0
HW
985\r
986 if (((ScsiIoDevice->ExtScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {\r
987 Status = ScsiIoDevice->ExtScsiPassThru->PassThru (\r
988 ScsiIoDevice->ExtScsiPassThru,\r
989 Target,\r
990 ScsiIoDevice->Lun,\r
991 ExtRequestPacket,\r
992 Event\r
993 );\r
994 } else {\r
995 //\r
996 // If there's no event or the SCSI Device doesn't support NON-BLOCKING,\r
997 // let the 'Event' parameter for PassThru() be NULL.\r
998 //\r
999 Status = ScsiIoDevice->ExtScsiPassThru->PassThru (\r
1000 ScsiIoDevice->ExtScsiPassThru,\r
1001 Target,\r
1002 ScsiIoDevice->Lun,\r
1003 ExtRequestPacket,\r
1004 NULL\r
1005 );\r
1436aea4 1006 if ((!EFI_ERROR (Status)) && (Event != NULL)) {\r
0d12e6a0 1007 //\r
9f840a9e
HW
1008 // Signal Event to tell caller to pick up the SCSI IO packet if the\r
1009 // PassThru() succeeds.\r
0d12e6a0
HW
1010 //\r
1011 gBS->SignalEvent (Event);\r
1012 }\r
1013 }\r
70c94b3b 1014 } else {\r
1436aea4 1015 mWorkingBuffer = AllocatePool (sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
3a10d471 1016\r
9b38ff34 1017 if (mWorkingBuffer == NULL) {\r
70c94b3b 1018 return EFI_DEVICE_ERROR;\r
1019 }\r
1020\r
1021 //\r
c52fa98c 1022 // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.\r
70c94b3b 1023 //\r
1436aea4
MK
1024 Status = ScsiioToPassThruPacket (Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *)mWorkingBuffer);\r
1025 if (EFI_ERROR (Status)) {\r
1026 FreePool (mWorkingBuffer);\r
70c94b3b 1027 return Status;\r
1028 }\r
1029\r
7077edb3 1030 if (((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {\r
1436aea4 1031 EventData.Data1 = (VOID *)Packet;\r
70c94b3b 1032 EventData.Data2 = Event;\r
1033 //\r
1034 // Create Event\r
1035 //\r
1036 Status = gBS->CreateEvent (\r
1436aea4
MK
1037 EVT_NOTIFY_SIGNAL,\r
1038 TPL_NOTIFY,\r
1039 NotifyFunction,\r
1040 &EventData,\r
1041 &PacketEvent\r
1042 );\r
1043 if (EFI_ERROR (Status)) {\r
1044 FreePool (mWorkingBuffer);\r
70c94b3b 1045 return Status;\r
1046 }\r
c52fa98c 1047\r
70c94b3b 1048 Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
1436aea4
MK
1049 ScsiIoDevice->ScsiPassThru,\r
1050 ScsiIoDevice->Pun.ScsiId.Scsi,\r
1051 ScsiIoDevice->Lun,\r
1052 mWorkingBuffer,\r
1053 PacketEvent\r
1054 );\r
70c94b3b 1055\r
1436aea4
MK
1056 if (EFI_ERROR (Status)) {\r
1057 FreePool (mWorkingBuffer);\r
1058 gBS->CloseEvent (PacketEvent);\r
70c94b3b 1059 return Status;\r
1060 }\r
70c94b3b 1061 } else {\r
1062 //\r
1063 // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert\r
1064 // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet.\r
1065 //\r
1066 Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
1436aea4
MK
1067 ScsiIoDevice->ScsiPassThru,\r
1068 ScsiIoDevice->Pun.ScsiId.Scsi,\r
1069 ScsiIoDevice->Lun,\r
1070 mWorkingBuffer,\r
1071 NULL\r
1072 );\r
1073 if (EFI_ERROR (Status)) {\r
1074 FreePool (mWorkingBuffer);\r
70c94b3b 1075 return Status;\r
1076 }\r
1077\r
1436aea4 1078 PassThruToScsiioPacket ((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *)mWorkingBuffer, Packet);\r
70c94b3b 1079 //\r
1080 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,\r
9beb888e 1081 // free mWorkingBuffer.\r
70c94b3b 1082 //\r
1436aea4 1083 FreePool (mWorkingBuffer);\r
0d12e6a0
HW
1084\r
1085 //\r
1086 // Signal Event to tell caller to pick up the SCSI IO Packet.\r
1087 //\r
1088 if (Event != NULL) {\r
1089 gBS->SignalEvent (Event);\r
1090 }\r
70c94b3b 1091 }\r
1092 }\r
1436aea4 1093\r
3a10d471 1094 return Status;\r
1095}\r
1096\r
9beb888e 1097/**\r
70c94b3b 1098 Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\r
3a10d471 1099\r
9beb888e 1100 @param This Protocol instance pointer\r
1101 @param Controller Controller handle\r
cc530cd1 1102 @param TargetId Target to be scanned\r
9beb888e 1103 @param Lun The Lun of the SCSI device on the SCSI channel.\r
1104 @param ScsiBusDev The pointer of SCSI_BUS_DEVICE\r
3a10d471 1105\r
9beb888e 1106 @retval EFI_SUCCESS Successfully to discover the device and attach\r
1107 ScsiIoProtocol to it.\r
d375273c
YY
1108 @retval EFI_NOT_FOUND Fail to discover the device.\r
1109 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resources.\r
3a10d471 1110\r
9beb888e 1111**/\r
1112EFI_STATUS\r
1113EFIAPI\r
1114ScsiScanCreateDevice (\r
1436aea4
MK
1115 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1116 IN EFI_HANDLE Controller,\r
1117 IN SCSI_TARGET_ID *TargetId,\r
1118 IN UINT64 Lun,\r
1119 IN OUT SCSI_BUS_DEVICE *ScsiBusDev\r
9beb888e 1120 )\r
3a10d471 1121{\r
1122 EFI_STATUS Status;\r
1123 SCSI_IO_DEV *ScsiIoDevice;\r
1124 EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;\r
cbd2a4b3 1125 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1126 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
1436aea4 1127 EFI_HANDLE DeviceHandle;\r
cbd2a4b3 1128\r
1129 DevicePath = NULL;\r
1130 RemainingDevicePath = NULL;\r
1131 ScsiDevicePath = NULL;\r
1132 ScsiIoDevice = NULL;\r
1133\r
1134 //\r
1135 // Build Device Path\r
1136 //\r
1436aea4 1137 if (ScsiBusDev->ExtScsiSupport) {\r
cbd2a4b3 1138 Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (\r
1139 ScsiBusDev->ExtScsiInterface,\r
1140 &TargetId->ScsiId.ExtScsi[0],\r
1141 Lun,\r
1142 &ScsiDevicePath\r
1143 );\r
1144 } else {\r
e7c2a83b 1145 Status = ScsiBusDev->ScsiInterface->BuildDevicePath (\r
1146 ScsiBusDev->ScsiInterface,\r
1147 TargetId->ScsiId.Scsi,\r
1148 Lun,\r
1149 &ScsiDevicePath\r
1150 );\r
cbd2a4b3 1151 }\r
1152\r
1436aea4 1153 if (EFI_ERROR (Status)) {\r
cbd2a4b3 1154 return Status;\r
1155 }\r
1156\r
1157 DevicePath = AppendDevicePathNode (\r
1158 ScsiBusDev->DevicePath,\r
1159 ScsiDevicePath\r
1160 );\r
1161\r
1162 if (DevicePath == NULL) {\r
1163 Status = EFI_OUT_OF_RESOURCES;\r
1164 goto ErrorExit;\r
1165 }\r
1166\r
1436aea4 1167 DeviceHandle = NULL;\r
cbd2a4b3 1168 RemainingDevicePath = DevicePath;\r
1436aea4
MK
1169 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
1170 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd (RemainingDevicePath)) {\r
cbd2a4b3 1171 //\r
1172 // The device has been started, directly return to fast boot.\r
1173 //\r
1174 Status = EFI_ALREADY_STARTED;\r
1175 goto ErrorExit;\r
1176 }\r
3a10d471 1177\r
9beb888e 1178 ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));\r
1179 if (ScsiIoDevice == NULL) {\r
cbd2a4b3 1180 Status = EFI_OUT_OF_RESOURCES;\r
1181 goto ErrorExit;\r
3a10d471 1182 }\r
1183\r
1436aea4
MK
1184 ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;\r
1185 ScsiIoDevice->ScsiBusDeviceData = ScsiBusDev;\r
1186 CopyMem (&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);\r
1187 ScsiIoDevice->Lun = Lun;\r
3a10d471 1188\r
70c94b3b 1189 if (ScsiBusDev->ExtScsiSupport) {\r
1436aea4
MK
1190 ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface;\r
1191 ScsiIoDevice->ExtScsiSupport = TRUE;\r
1192 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;\r
70c94b3b 1193 } else {\r
1436aea4
MK
1194 ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface;\r
1195 ScsiIoDevice->ExtScsiSupport = FALSE;\r
1196 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;\r
70c94b3b 1197 }\r
1198\r
3a10d471 1199 ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;\r
70c94b3b 1200 ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;\r
3a10d471 1201 ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;\r
1202 ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;\r
24e734d2 1203 ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
3a10d471 1204\r
37623a5c 1205 //\r
1206 // Report Status Code here since the new SCSI device will be discovered\r
1207 //\r
1208 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1209 EFI_PROGRESS_CODE,\r
1210 (EFI_IO_BUS_SCSI | EFI_IOB_PC_ENABLE),\r
1211 ScsiBusDev->DevicePath\r
1212 );\r
1213\r
d375273c
YY
1214 Status = DiscoverScsiDevice (ScsiIoDevice);\r
1215 if (EFI_ERROR (Status)) {\r
cbd2a4b3 1216 goto ErrorExit;\r
3a10d471 1217 }\r
70c94b3b 1218\r
cbd2a4b3 1219 ScsiIoDevice->DevicePath = DevicePath;\r
c52fa98c 1220\r
3a10d471 1221 Status = gBS->InstallMultipleProtocolInterfaces (\r
1222 &ScsiIoDevice->Handle,\r
1223 &gEfiDevicePathProtocolGuid,\r
1224 ScsiIoDevice->DevicePath,\r
1225 &gEfiScsiIoProtocolGuid,\r
1226 &ScsiIoDevice->ScsiIo,\r
1227 NULL\r
1228 );\r
1229 if (EFI_ERROR (Status)) {\r
cbd2a4b3 1230 goto ErrorExit;\r
3a10d471 1231 } else {\r
70c94b3b 1232 if (ScsiBusDev->ExtScsiSupport) {\r
1233 gBS->OpenProtocol (\r
cbd2a4b3 1234 Controller,\r
1235 &gEfiExtScsiPassThruProtocolGuid,\r
1436aea4 1236 (VOID **)&(ScsiBusDev->ExtScsiInterface),\r
cbd2a4b3 1237 This->DriverBindingHandle,\r
1238 ScsiIoDevice->Handle,\r
1239 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1240 );\r
1436aea4 1241 } else {\r
70c94b3b 1242 gBS->OpenProtocol (\r
cbd2a4b3 1243 Controller,\r
1244 &gEfiScsiPassThruProtocolGuid,\r
1436aea4 1245 (VOID **)&(ScsiBusDev->ScsiInterface),\r
cbd2a4b3 1246 This->DriverBindingHandle,\r
1247 ScsiIoDevice->Handle,\r
1248 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1249 );\r
1436aea4 1250 }\r
3a10d471 1251 }\r
1436aea4 1252\r
3a10d471 1253 return EFI_SUCCESS;\r
cbd2a4b3 1254\r
1255ErrorExit:\r
d1102dba 1256\r
cbd2a4b3 1257 //\r
1258 // The memory space for ScsiDevicePath is allocated in\r
1259 // ScsiPassThru->BuildDevicePath() function; It is no longer used\r
1260 // after AppendDevicePathNode,so free the memory it occupies.\r
1261 //\r
1262 FreePool (ScsiDevicePath);\r
1263\r
1264 if (DevicePath != NULL) {\r
1265 FreePool (DevicePath);\r
1266 }\r
1267\r
1268 if (ScsiIoDevice != NULL) {\r
1269 FreePool (ScsiIoDevice);\r
1270 }\r
1271\r
1272 return Status;\r
3a10d471 1273}\r
1274\r
9beb888e 1275/**\r
70c94b3b 1276 Discovery SCSI Device\r
3a10d471 1277\r
9beb888e 1278 @param ScsiIoDevice The pointer of SCSI_IO_DEV\r
3a10d471 1279\r
d375273c
YY
1280 @retval EFI_SUCCESS Find SCSI Device and verify it.\r
1281 @retval EFI_NOT_FOUND Unable to find SCSI Device.\r
1282 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resources.\r
3a10d471 1283\r
9beb888e 1284**/\r
d375273c 1285EFI_STATUS\r
9beb888e 1286DiscoverScsiDevice (\r
1436aea4 1287 IN OUT SCSI_IO_DEV *ScsiIoDevice\r
9beb888e 1288 )\r
3a10d471 1289{\r
1436aea4
MK
1290 EFI_STATUS Status;\r
1291 UINT32 InquiryDataLength;\r
1292 UINT8 SenseDataLength;\r
1293 UINT8 HostAdapterStatus;\r
1294 UINT8 TargetStatus;\r
1295 EFI_SCSI_INQUIRY_DATA *InquiryData;\r
1296 EFI_SCSI_SENSE_DATA *SenseData;\r
1297 UINT8 MaxRetry;\r
1298 UINT8 Index;\r
3a10d471 1299\r
1300 HostAdapterStatus = 0;\r
1301 TargetStatus = 0;\r
ce13d2d8 1302 SenseData = NULL;\r
957fe093
SZ
1303\r
1304 InquiryData = AllocateAlignedBuffer (ScsiIoDevice, sizeof (EFI_SCSI_INQUIRY_DATA));\r
1305 if (InquiryData == NULL) {\r
d375273c 1306 Status = EFI_OUT_OF_RESOURCES;\r
957fe093
SZ
1307 goto Done;\r
1308 }\r
1309\r
ce13d2d8
LE
1310 SenseData = AllocateAlignedBuffer (\r
1311 ScsiIoDevice,\r
1312 sizeof (EFI_SCSI_SENSE_DATA)\r
1313 );\r
1314 if (SenseData == NULL) {\r
d375273c 1315 Status = EFI_OUT_OF_RESOURCES;\r
ce13d2d8
LE
1316 goto Done;\r
1317 }\r
1318\r
3a10d471 1319 //\r
1320 // Using Inquiry command to scan for the device\r
1321 //\r
1322 InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);\r
ce13d2d8 1323 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);\r
957fe093 1324 ZeroMem (InquiryData, InquiryDataLength);\r
ce13d2d8 1325 ZeroMem (SenseData, SenseDataLength);\r
cbd2a4b3 1326\r
1327 MaxRetry = 2;\r
1328 for (Index = 0; Index < MaxRetry; Index++) {\r
1329 Status = ScsiInquiryCommand (\r
1436aea4
MK
1330 &ScsiIoDevice->ScsiIo,\r
1331 SCSI_BUS_TIMEOUT,\r
1332 SenseData,\r
1333 &SenseDataLength,\r
1334 &HostAdapterStatus,\r
1335 &TargetStatus,\r
1336 (VOID *)InquiryData,\r
1337 &InquiryDataLength,\r
1338 FALSE\r
1339 );\r
cbd2a4b3 1340 if (!EFI_ERROR (Status)) {\r
ce13d2d8
LE
1341 if ((HostAdapterStatus == EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK) &&\r
1342 (TargetStatus == EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION) &&\r
1343 (SenseData->Error_Code == 0x70) &&\r
1436aea4
MK
1344 (SenseData->Sense_Key == EFI_SCSI_SK_ILLEGAL_REQUEST))\r
1345 {\r
d375273c 1346 Status = EFI_NOT_FOUND;\r
ce13d2d8
LE
1347 goto Done;\r
1348 }\r
1436aea4 1349\r
cbd2a4b3 1350 break;\r
c09e481b 1351 }\r
1436aea4 1352\r
c09e481b
LE
1353 if ((Status == EFI_BAD_BUFFER_SIZE) ||\r
1354 (Status == EFI_INVALID_PARAMETER) ||\r
1436aea4
MK
1355 (Status == EFI_UNSUPPORTED))\r
1356 {\r
d375273c 1357 Status = EFI_NOT_FOUND;\r
957fe093 1358 goto Done;\r
cbd2a4b3 1359 }\r
1360 }\r
3a10d471 1361\r
cbd2a4b3 1362 if (Index == MaxRetry) {\r
d375273c 1363 Status = EFI_NOT_FOUND;\r
957fe093 1364 goto Done;\r
3a10d471 1365 }\r
d1102dba 1366\r
3a10d471 1367 //\r
1368 // Retrieved inquiry data successfully\r
1369 //\r
897efb97 1370 if (InquiryData->Peripheral_Qualifier != 0) {\r
d375273c 1371 Status = EFI_NOT_FOUND;\r
957fe093 1372 goto Done;\r
3a10d471 1373 }\r
1374\r
1ff7ed2c 1375 if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&\r
1436aea4
MK
1376 (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH))\r
1377 {\r
d375273c 1378 Status = EFI_NOT_FOUND;\r
957fe093 1379 goto Done;\r
3a10d471 1380 }\r
c52fa98c 1381\r
3a10d471 1382 //\r
1383 // valid device type and peripheral qualifier combination.\r
1384 //\r
957fe093
SZ
1385 ScsiIoDevice->ScsiDeviceType = InquiryData->Peripheral_Type;\r
1386 ScsiIoDevice->RemovableDevice = InquiryData->Rmb;\r
1387 if (InquiryData->Version == 0) {\r
3a10d471 1388 ScsiIoDevice->ScsiVersion = 0;\r
1389 } else {\r
1390 //\r
1391 // ANSI-approved version\r
1392 //\r
1436aea4 1393 ScsiIoDevice->ScsiVersion = (UINT8)(InquiryData->Version & 0x07);\r
3a10d471 1394 }\r
1395\r
d375273c 1396 Status = EFI_SUCCESS;\r
957fe093
SZ
1397\r
1398Done:\r
ce13d2d8 1399 FreeAlignedBuffer (SenseData, sizeof (EFI_SCSI_SENSE_DATA));\r
957fe093
SZ
1400 FreeAlignedBuffer (InquiryData, sizeof (EFI_SCSI_INQUIRY_DATA));\r
1401\r
d375273c 1402 return Status;\r
3a10d471 1403}\r
70c94b3b 1404\r
9beb888e 1405/**\r
1406 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.\r
1407\r
1408 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
1409 @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
1410\r
1411**/\r
70c94b3b 1412EFI_STATUS\r
1413EFIAPI\r
1414ScsiioToPassThruPacket (\r
1415 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,\r
9beb888e 1416 OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket\r
70c94b3b 1417 )\r
70c94b3b 1418{\r
1419 //\r
1436aea4 1420 // EFI 1.10 doesn't support Bi-Direction Command.\r
70c94b3b 1421 //\r
1422 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {\r
1423 return EFI_UNSUPPORTED;\r
1424 }\r
c52fa98c 1425\r
70c94b3b 1426 ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
1427\r
1428 CommandPacket->Timeout = Packet->Timeout;\r
1429 CommandPacket->Cdb = Packet->Cdb;\r
1430 CommandPacket->CdbLength = Packet->CdbLength;\r
1431 CommandPacket->DataDirection = Packet->DataDirection;\r
1432 CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus;\r
1433 CommandPacket->TargetStatus = Packet->TargetStatus;\r
1434 CommandPacket->SenseData = Packet->SenseData;\r
1435 CommandPacket->SenseDataLength = Packet->SenseDataLength;\r
1436\r
1437 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
1436aea4 1438 CommandPacket->DataBuffer = Packet->InDataBuffer;\r
70c94b3b 1439 CommandPacket->TransferLength = Packet->InTransferLength;\r
1440 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {\r
1436aea4 1441 CommandPacket->DataBuffer = Packet->OutDataBuffer;\r
70c94b3b 1442 CommandPacket->TransferLength = Packet->OutTransferLength;\r
1443 }\r
1436aea4 1444\r
70c94b3b 1445 return EFI_SUCCESS;\r
1446}\r
1447\r
9beb888e 1448/**\r
1449 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.\r
1450\r
1451 @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
1452 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
1453\r
1454**/\r
70c94b3b 1455EFI_STATUS\r
1456EFIAPI\r
1457PassThruToScsiioPacket (\r
1458 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,\r
9beb888e 1459 OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet\r
70c94b3b 1460 )\r
70c94b3b 1461{\r
1462 Packet->Timeout = ScsiPacket->Timeout;\r
1463 Packet->Cdb = ScsiPacket->Cdb;\r
1464 Packet->CdbLength = ScsiPacket->CdbLength;\r
1465 Packet->DataDirection = ScsiPacket->DataDirection;\r
1466 Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus;\r
1467 Packet->TargetStatus = ScsiPacket->TargetStatus;\r
1468 Packet->SenseData = ScsiPacket->SenseData;\r
1469 Packet->SenseDataLength = ScsiPacket->SenseDataLength;\r
1470\r
1471 if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
1436aea4 1472 Packet->InDataBuffer = ScsiPacket->DataBuffer;\r
70c94b3b 1473 Packet->InTransferLength = ScsiPacket->TransferLength;\r
1474 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {\r
1436aea4 1475 Packet->OutDataBuffer = ScsiPacket->DataBuffer;\r
70c94b3b 1476 Packet->OutTransferLength = ScsiPacket->TransferLength;\r
1477 }\r
c52fa98c 1478\r
70c94b3b 1479 return EFI_SUCCESS;\r
1480}\r
1481\r
9beb888e 1482/**\r
1483 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0\r
1484 SCSI IO Packet.\r
70c94b3b 1485\r
9beb888e 1486 @param Event The instance of EFI_EVENT.\r
1487 @param Context The parameter passed in.\r
70c94b3b 1488\r
9beb888e 1489**/\r
70c94b3b 1490VOID\r
1491EFIAPI\r
1492NotifyFunction (\r
9beb888e 1493 IN EFI_EVENT Event,\r
1494 IN VOID *Context\r
70c94b3b 1495 )\r
70c94b3b 1496{\r
1436aea4
MK
1497 EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet;\r
1498 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket;\r
1499 EFI_EVENT CallerEvent;\r
1500 SCSI_EVENT_DATA *PassData;\r
70c94b3b 1501\r
1436aea4
MK
1502 PassData = (SCSI_EVENT_DATA *)Context;\r
1503 Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;\r
1504 ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *)mWorkingBuffer;\r
70c94b3b 1505\r
1506 //\r
1507 // Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.\r
1508 //\r
1436aea4 1509 PassThruToScsiioPacket (ScsiPacket, Packet);\r
c52fa98c 1510\r
70c94b3b 1511 //\r
1512 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,\r
9beb888e 1513 // free mWorkingBuffer.\r
70c94b3b 1514 //\r
1436aea4 1515 gBS->FreePool (mWorkingBuffer);\r
70c94b3b 1516\r
1517 //\r
1518 // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.\r
1519 //\r
1520 CallerEvent = PassData->Data2;\r
1436aea4
MK
1521 gBS->CloseEvent (Event);\r
1522 gBS->SignalEvent (CallerEvent);\r
70c94b3b 1523}\r