]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
Add runtime safe PCI Express Library instance
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
CommitLineData
bf231ea6
A
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
dfc5aca1 4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>\r
bf231ea6
A
5 All rights reserved. This program and the accompanying materials \r
6 are licensed and made available under the terms and conditions of the BSD License \r
7 which accompanies this distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
a02e796b 14\r
bf231ea6 15\r
60c93673 16#include <Uefi.h>\r
306431f7 17#include <Library/DebugLib.h>\r
172ea7c7 18#include <Library/UefiScsiLib.h>\r
a02e796b 19#include <Library/BaseMemoryLib.h>\r
d5954c61 20 \r
a3589760 21#include <IndustryStandard/Scsi.h>\r
d5954c61 22 \r
23 \r
24 //\r
25 // Max bytes needed to represent ID of a SCSI device\r
26 //\r
dfc5aca1 27#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
d5954c61 28 \r
29 //\r
30 // bit5..7 are for Logical unit number\r
31 // 11100000b (0xe0)\r
32 //\r
52cd71dc 33#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
d5954c61 34 \r
35 //\r
36 // Scsi Command Length six or ten\r
37 //\r
52cd71dc
LG
38#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
39#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
bf231ea6 40\r
b91d5eca 41\r
b91d5eca 42\r
d5954c61 43/**\r
44 Execute Test Unit Ready SCSI command on a specific SCSI target.\r
b91d5eca 45\r
d5954c61 46 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
47 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
48 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
49 If ScsiIo is NULL, then ASSERT().\r
50 If SenseDataLength is NULL, then ASSERT().\r
52cd71dc
LG
51 If HostAdapterStatus is NULL, then ASSERT().\r
52 If TargetStatus is NULL, then ASSERT().\r
a3589760 53\r
d5954c61 54\r
55 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
56 for the specific SCSI target.\r
57 @param[in] Timeout The timeout in 100 ns units to use for the execution\r
58 of this SCSI Request Packet. A Timeout value of\r
59 zero means that this function will wait indefinitely\r
60 for the SCSI Request Packet to execute. If Timeout\r
61 is greater than zero, then this function will return\r
62 EFI_TIMEOUT if the time required to execute the SCSI\r
63 Request Packet is greater than Timeout.\r
64 @param[in, out] SenseData A pointer to sense data that was generated by\r
65 the execution of the SCSI Request Packet. This\r
66 buffer must be allocated by the caller.\r
67 If SenseDataLength is 0, then this parameter is\r
68 optional and may be NULL.\r
69 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
70 the SenseData buffer. On output, a poiinter to\r
71 the number of bytes written to the SenseData buffer. \r
72 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
73 the SCSI bus containing the SCSI target specified by\r
74 ScsiIo when the SCSI Request Packet was executed.\r
75 See the EFI SCSI I/O Protocol in the UEFI Specification\r
76 for details on the possible return values.\r
77 @param[out] TargetStatus The status returned by the SCSI target specified\r
78 by ScsiIo when the SCSI Request Packat was executed\r
79 on the SCSI Host Controller. See the EFI SCSI I/O\r
80 Protocol in the UEFI Specification for details on\r
81 the possible return values. \r
82\r
83 @retval EFI_SUCCESS The command was executed successfully.\r
84 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
85 and SenseData in that order for additional status\r
86 information.\r
87 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
88 there are too many SCSI Command Packets already\r
89 queued. The SCSI Request Packet was not sent, so\r
90 no additional status information is available.\r
91 The caller may retry again later.\r
92 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
93 SCSI Request Packet. See HostAdapterStatus,\r
94 TargetStatus, SenseDataLength, and SenseData in that\r
95 order for additional status information.\r
96 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
97 is not supported by the SCSI initiator(i.e., SCSI\r
98 Host Controller). The SCSI Request Packet was not\r
99 sent, so no additional status information is available.\r
100 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
101 Packet to execute. See HostAdapterStatus, TargetStatus,\r
102 SenseDataLength, and SenseData in that order for\r
103 additional status information.\r
104 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
105 but the entire DataBuffer could not be transferred.\r
106 The actual number of bytes transferred is returned\r
107 in InTransferLength.\r
a3589760 108\r
bf231ea6 109**/\r
a02e796b 110EFI_STATUS\r
373b5cf9 111EFIAPI\r
d35be2a4 112ScsiTestUnitReadyCommand (\r
d5954c61 113 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
114 IN UINT64 Timeout,\r
115 IN OUT VOID *SenseData, OPTIONAL\r
116 IN OUT UINT8 *SenseDataLength,\r
117 OUT UINT8 *HostAdapterStatus,\r
118 OUT UINT8 *TargetStatus\r
a02e796b 119 )\r
a02e796b 120{\r
121 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
122 UINT64 Lun;\r
123 UINT8 *Target;\r
124 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
125 EFI_STATUS Status;\r
52cd71dc 126 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 127\r
8069d49e
LG
128 ASSERT (SenseDataLength != NULL);\r
129 ASSERT (HostAdapterStatus != NULL);\r
130 ASSERT (TargetStatus != NULL);\r
d5954c61 131 ASSERT (ScsiIo != NULL);\r
a02e796b 132\r
133 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 134 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 135\r
136 CommandPacket.Timeout = Timeout;\r
137 CommandPacket.InDataBuffer = NULL;\r
138 CommandPacket.InTransferLength= 0;\r
139 CommandPacket.OutDataBuffer = NULL;\r
140 CommandPacket.OutTransferLength= 0;\r
141 CommandPacket.SenseData = SenseData;\r
142 CommandPacket.Cdb = Cdb;\r
143 //\r
144 // Fill Cdb for Test Unit Ready Command\r
145 //\r
146 Target = &TargetArray[0];\r
147 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
148\r
149 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
52cd71dc
LG
150 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
151 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 152 CommandPacket.SenseDataLength = *SenseDataLength;\r
153\r
154 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
155\r
156 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
157 *TargetStatus = CommandPacket.TargetStatus;\r
158 *SenseDataLength = CommandPacket.SenseDataLength;\r
159\r
160 return Status;\r
161}\r
162\r
bf231ea6 163\r
a3589760 164/**\r
d5954c61 165 Execute Inquiry SCSI command on a specific SCSI target.\r
b91d5eca 166\r
d5954c61 167 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
168 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
169 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
170 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
171 If SenseDataLength is NULL, then ASSERT().\r
172 If HostAdapterStatus is NULL, then ASSERT().\r
173 If TargetStatus is NULL, then ASSERT().\r
174 If InquiryDataLength is NULL, then ASSERT().\r
a3589760 175\r
d5954c61 176 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
177 for the specific SCSI target.\r
178 @param[in] Timeout The timeout in 100 ns units to use for the\r
179 execution of this SCSI Request Packet. A Timeout\r
180 value of zero means that this function will wait\r
181 indefinitely for the SCSI Request Packet to execute.\r
182 If Timeout is greater than zero, then this function\r
183 will return EFI_TIMEOUT if the time required to\r
184 execute the SCSI Request Packet is greater than Timeout.\r
185 @param[in, out] SenseData A pointer to sense data that was generated\r
186 by the execution of the SCSI Request Packet.\r
187 This buffer must be allocated by the caller.\r
188 If SenseDataLength is 0, then this parameter\r
189 is optional and may be NULL.\r
190 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
191 On output, the number of bytes written to the SenseData buffer. \r
192 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
193 produces the SCSI bus containing the SCSI\r
194 target specified by ScsiIo when the SCSI\r
195 Request Packet was executed. See the EFI\r
196 SCSI I/O Protocol in the UEFI Specification\r
197 for details on the possible return values.\r
198 @param[out] TargetStatus The status returned by the SCSI target specified\r
199 by ScsiIo when the SCSI Request Packat was\r
200 executed on the SCSI Host Controller.\r
201 See the EFI SCSI I/O Protocol in the UEFI\r
202 Specification for details on the possible\r
203 return values. \r
204 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
205 by the execution of the SCSI Request Packet.\r
206 This buffer must be allocated by the caller.\r
207 If InquiryDataLength is 0, then this parameter\r
208 is optional and may be NULL. \r
209 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
210 of the InquiryDataBuffer buffer.\r
211 On output, a pointer to the number of bytes\r
212 written to the InquiryDataBuffer buffer.\r
213 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
214 data is returned in InquiryDataBuffer.\r
215 If FALSE, then the standard inquiry data is\r
216 returned in InquiryDataBuffer. \r
217\r
218 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,\r
219 TargetStatus, SenseDataLength, and SenseData in that order\r
220 for additional status information.\r
221 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
222 InquiryDataBuffer could not be transferred. The actual\r
223 number of bytes transferred is returned in InquiryDataLength.\r
224 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
225 are too many SCSI Command Packets already queued.\r
226 The SCSI Request Packet was not sent, so no additional\r
227 status information is available. The caller may retry again later.\r
228 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
229 Request Packet. See HostAdapterStatus, TargetStatus,\r
230 SenseDataLength, and SenseData in that order for additional\r
231 status information.\r
232 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
233 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
234 The SCSI Request Packet was not sent, so no additional\r
235 status information is available.\r
236 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
237 Packet to execute. See HostAdapterStatus, TargetStatus,\r
238 SenseDataLength, and SenseData in that order for\r
239 additional status information.\r
a3589760 240\r
bf231ea6 241**/\r
a02e796b 242EFI_STATUS\r
373b5cf9 243EFIAPI\r
d35be2a4 244ScsiInquiryCommand (\r
d5954c61 245 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
246 IN UINT64 Timeout,\r
247 IN OUT VOID *SenseData, OPTIONAL\r
248 IN OUT UINT8 *SenseDataLength,\r
249 OUT UINT8 *HostAdapterStatus,\r
250 OUT UINT8 *TargetStatus,\r
251 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
252 IN OUT UINT32 *InquiryDataLength,\r
253 IN BOOLEAN EnableVitalProductData\r
a02e796b 254 )\r
a02e796b 255{\r
256 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
257 UINT64 Lun;\r
258 UINT8 *Target;\r
259 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
260 EFI_STATUS Status;\r
52cd71dc 261 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 262\r
8069d49e
LG
263 ASSERT (SenseDataLength != NULL);\r
264 ASSERT (HostAdapterStatus != NULL);\r
265 ASSERT (TargetStatus != NULL);\r
266 ASSERT (InquiryDataLength != NULL);\r
d5954c61 267 ASSERT (ScsiIo != NULL);\r
8069d49e 268\r
a02e796b 269 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 270 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 271\r
272 CommandPacket.Timeout = Timeout;\r
273 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
274 CommandPacket.InTransferLength= *InquiryDataLength;\r
275 CommandPacket.SenseData = SenseData;\r
276 CommandPacket.SenseDataLength = *SenseDataLength;\r
277 CommandPacket.Cdb = Cdb;\r
278\r
279 Target = &TargetArray[0];\r
280 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
281\r
282 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
52cd71dc 283 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 284 if (EnableVitalProductData) {\r
285 Cdb[1] |= 0x01;\r
286 }\r
287\r
288 if (*InquiryDataLength > 0xff) {\r
289 *InquiryDataLength = 0xff;\r
290 }\r
291\r
292 Cdb[4] = (UINT8) (*InquiryDataLength);\r
52cd71dc 293 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 294 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
295\r
296 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
297\r
298 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
299 *TargetStatus = CommandPacket.TargetStatus;\r
300 *SenseDataLength = CommandPacket.SenseDataLength;\r
301 *InquiryDataLength = CommandPacket.InTransferLength;\r
302\r
303 return Status;\r
304}\r
305\r
bf231ea6 306\r
a3589760 307/**\r
d5954c61 308 Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
309\r
310 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
311 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
312 If Timeout is greater than zero, then the command is executed and will timeout\r
313 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
314 are used to construct the CDB for this SCSI command.\r
315 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
316 If SenseDataLength is NULL, then ASSERT().\r
317 If HostAdapterStatus is NULL, then ASSERT().\r
318 If TargetStatus is NULL, then ASSERT().\r
319 If DataLength is NULL, then ASSERT().\r
a3589760 320\r
d5954c61 321\r
322 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
323 for the specific SCSI target.\r
324 @param[in] Timeout The timeout in 100 ns units to use for the\r
325 execution of this SCSI Request Packet. A Timeout\r
326 value of zero means that this function will wait\r
327 indefinitely for the SCSI Request Packet to execute.\r
328 If Timeout is greater than zero, then this function\r
329 will return EFI_TIMEOUT if the time required to\r
330 execute the SCSI Request Packet is greater than Timeout.\r
331 @param[in, out] SenseData A pointer to sense data that was generated\r
332 by the execution of the SCSI Request Packet.\r
333 This buffer must be allocated by the caller.\r
334 If SenseDataLength is 0, then this parameter\r
335 is optional and may be NULL.\r
336 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
337 On output, the number of bytes written to the SenseData buffer. \r
338 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
339 produces the SCSI bus containing the SCSI target\r
340 specified by ScsiIo when the SCSI Request Packet\r
341 was executed. See the EFI SCSI I/O Protocol in the\r
342 UEFI Specification for details on the possible\r
343 return values.\r
344 @param[out] TargetStatus The status returned by the SCSI target specified\r
345 by ScsiIo when the SCSI Request Packat was executed\r
346 on the SCSI Host Controller. See the EFI SCSI\r
347 I/O Protocol in the UEFI Specification for details\r
348 on the possible return values.\r
349 @param[in, out] DataBuffer A pointer to data that was generated by the\r
350 execution of the SCSI Request Packet. This\r
351 buffer must be allocated by the caller. If\r
352 DataLength is 0, then this parameter is optional\r
353 and may be NULL. \r
354 @param[in, out] DataLength On input, a pointer to the length in bytes of\r
355 the DataBuffer buffer. On output, a pointer\r
356 to the number of bytes written to the DataBuffer\r
357 buffer. \r
358 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
359 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. \r
360 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. \r
361\r
362 @retval EFI_SUCCESS The command was executed successfully.\r
363 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
364 and SenseData in that order for additional status information.\r
365 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
366 entire DataBuffer could not be transferred.\r
bf231ea6 367 The actual number of bytes transferred is returned\r
d5954c61 368 in DataLength.\r
369 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
370 there are too many SCSI Command Packets already queued.\r
371 The SCSI Request Packet was not sent, so no additional\r
372 status information is available. The caller may retry\r
373 again later.\r
374 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
375 SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
376 SenseDataLength, and SenseData in that order for\r
377 additional status information.\r
bf231ea6 378 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
d5954c61 379 is not supported by the SCSI initiator(i.e., SCSI\r
380 Host Controller). The SCSI Request Packet was not\r
381 sent, so no additional status information is available.\r
382 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
383 Request Packet to execute. See HostAdapterStatus,\r
384 TargetStatus, SenseDataLength, and SenseData in that\r
385 order for additional status information.\r
a3589760 386\r
bf231ea6 387**/\r
a02e796b 388EFI_STATUS\r
373b5cf9 389EFIAPI\r
d35be2a4 390ScsiModeSense10Command (\r
d5954c61 391 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
392 IN UINT64 Timeout,\r
393 IN OUT VOID *SenseData, OPTIONAL\r
394 IN OUT UINT8 *SenseDataLength,\r
395 OUT UINT8 *HostAdapterStatus,\r
396 OUT UINT8 *TargetStatus,\r
397 IN OUT VOID *DataBuffer, OPTIONAL\r
398 IN OUT UINT32 *DataLength,\r
399 IN UINT8 DBDField, OPTIONAL\r
400 IN UINT8 PageControl,\r
401 IN UINT8 PageCode\r
a02e796b 402 )\r
a02e796b 403{\r
404 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
405 UINT64 Lun;\r
406 UINT8 *Target;\r
407 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
408 EFI_STATUS Status;\r
52cd71dc 409 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 410\r
8069d49e
LG
411 ASSERT (SenseDataLength != NULL);\r
412 ASSERT (HostAdapterStatus != NULL);\r
413 ASSERT (TargetStatus != NULL);\r
414 ASSERT (DataLength != NULL);\r
d5954c61 415 ASSERT (ScsiIo != NULL);\r
8069d49e 416\r
a02e796b 417 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 418 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 419\r
420 CommandPacket.Timeout = Timeout;\r
421 CommandPacket.InDataBuffer = DataBuffer;\r
422 CommandPacket.SenseData = SenseData;\r
423 CommandPacket.InTransferLength= *DataLength;\r
424 CommandPacket.Cdb = Cdb;\r
425 //\r
426 // Fill Cdb for Mode Sense (10) Command\r
427 //\r
428 Target = &TargetArray[0];\r
429 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
430\r
431 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
52cd71dc
LG
432 //\r
433 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
434 //\r
435 Cdb[1] = (UINT8) ((Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));\r
436 //\r
437 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
438 //\r
a02e796b 439 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));\r
440 Cdb[7] = (UINT8) (*DataLength >> 8);\r
441 Cdb[8] = (UINT8) (*DataLength);\r
442\r
52cd71dc 443 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 444 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
445 CommandPacket.SenseDataLength = *SenseDataLength;\r
446\r
447 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
448\r
449 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
450 *TargetStatus = CommandPacket.TargetStatus;\r
451 *SenseDataLength = CommandPacket.SenseDataLength;\r
452 *DataLength = CommandPacket.InTransferLength;\r
453\r
454 return Status;\r
455}\r
456\r
bf231ea6 457\r
a3589760 458/**\r
d5954c61 459 Execute Request Sense SCSI command on a specific SCSI target.\r
b91d5eca 460\r
d5954c61 461 Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
462 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
463 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
464 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
465 If SenseDataLength is NULL, then ASSERT().\r
466 If HostAdapterStatus is NULL, then ASSERT().\r
467 If TargetStatus is NULL, then ASSERT().\r
a3589760 468\r
b91d5eca 469 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
470 @param[in] Timeout The length of timeout period.\r
d5954c61 471 @param[in, out] SenseData A pointer to output sense data.\r
472 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 473 @param[out] HostAdapterStatus The status of Host Adapter.\r
474 @param[out] TargetStatus The status of the target.\r
475\r
476 @retval EFI_SUCCESS Command is executed successfully.\r
477 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
478 too many SCSI Command Packets already queued.\r
479 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
480 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
481 the SCSI initiator(i.e., SCSI Host Controller)\r
482 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 483\r
bf231ea6 484**/\r
a02e796b 485EFI_STATUS\r
373b5cf9 486EFIAPI\r
d35be2a4 487ScsiRequestSenseCommand (\r
d5954c61 488 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
489 IN UINT64 Timeout,\r
490 IN OUT VOID *SenseData, OPTIONAL\r
491 IN OUT UINT8 *SenseDataLength,\r
492 OUT UINT8 *HostAdapterStatus,\r
493 OUT UINT8 *TargetStatus\r
a02e796b 494 )\r
a02e796b 495{\r
496 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
497 UINT64 Lun;\r
498 UINT8 *Target;\r
499 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
500 EFI_STATUS Status;\r
52cd71dc 501 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 502\r
8069d49e
LG
503 ASSERT (SenseDataLength != NULL);\r
504 ASSERT (HostAdapterStatus != NULL);\r
505 ASSERT (TargetStatus != NULL);\r
d5954c61 506 ASSERT (ScsiIo != NULL);\r
8069d49e 507\r
a02e796b 508 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 509 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 510\r
511 CommandPacket.Timeout = Timeout;\r
512 CommandPacket.InDataBuffer = SenseData;\r
513 CommandPacket.SenseData = NULL;\r
514 CommandPacket.InTransferLength= *SenseDataLength;\r
515 CommandPacket.Cdb = Cdb;\r
516 //\r
517 // Fill Cdb for Request Sense Command\r
518 //\r
519 Target = &TargetArray[0];\r
520 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
521\r
522 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
52cd71dc 523 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 524 Cdb[4] = (UINT8) (*SenseDataLength);\r
525\r
52cd71dc 526 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 527 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
528 CommandPacket.SenseDataLength = 0;\r
529\r
530 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
531\r
532 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
533 *TargetStatus = CommandPacket.TargetStatus;\r
534 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
535\r
536 return Status;\r
537}\r
538\r
bf231ea6 539\r
a3589760 540/**\r
d5954c61 541 Execute Read Capacity SCSI command on a specific SCSI target.\r
b91d5eca 542\r
d5954c61 543 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
544 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
545 If Timeout is greater than zero, then the command is executed and will timeout after\r
546 Timeout 100 ns units. The PMI parameter is used to construct the CDB for this SCSI command.\r
547 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
548 If SenseDataLength is NULL, then ASSERT().\r
549 If HostAdapterStatus is NULL, then ASSERT().\r
550 If TargetStatus is NULL, then ASSERT().\r
551 If DataLength is NULL, then ASSERT().\r
bf231ea6 552\r
d5954c61 553 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
554 @param[in] Timeout The length of timeout period.\r
555 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 556 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 557 @param[out] HostAdapterStatus The status of Host Adapter.\r
558 @param[out] TargetStatus The status of the target.\r
559 @param[in, out] DataBuffer A pointer to a data buffer.\r
ee256e2c 560 @param[in, out] DataLength The length of data buffer.\r
d5954c61 561 @param[in] PMI Partial medium indicator.\r
b91d5eca 562\r
563 @retval EFI_SUCCESS Command is executed successfully.\r
564 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
565 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
566 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
567 SCSI Command Packets already queued.\r
568 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
569 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
570 the SCSI initiator(i.e., SCSI Host Controller)\r
571 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 572\r
bf231ea6 573**/\r
a02e796b 574EFI_STATUS\r
373b5cf9 575EFIAPI\r
d35be2a4 576ScsiReadCapacityCommand (\r
d5954c61 577 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
578 IN UINT64 Timeout,\r
579 IN OUT VOID *SenseData, OPTIONAL\r
580 IN OUT UINT8 *SenseDataLength,\r
581 OUT UINT8 *HostAdapterStatus,\r
582 OUT UINT8 *TargetStatus,\r
583 IN OUT VOID *DataBuffer, OPTIONAL\r
584 IN OUT UINT32 *DataLength,\r
585 IN BOOLEAN PMI\r
a02e796b 586 )\r
a02e796b 587{\r
588 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
589 UINT64 Lun;\r
590 UINT8 *Target;\r
591 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
592 EFI_STATUS Status;\r
52cd71dc 593 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 594\r
8069d49e
LG
595 ASSERT (SenseDataLength != NULL);\r
596 ASSERT (HostAdapterStatus != NULL);\r
597 ASSERT (TargetStatus != NULL);\r
598 ASSERT (DataLength != NULL);\r
d5954c61 599 ASSERT (ScsiIo != NULL);\r
8069d49e 600\r
a02e796b 601 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 602 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 603\r
604 CommandPacket.Timeout = Timeout;\r
605 CommandPacket.InDataBuffer = DataBuffer;\r
606 CommandPacket.SenseData = SenseData;\r
607 CommandPacket.InTransferLength= *DataLength;\r
608 CommandPacket.Cdb = Cdb;\r
609 //\r
610 // Fill Cdb for Read Capacity Command\r
611 //\r
612 Target = &TargetArray[0];\r
613 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
614\r
615 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
52cd71dc 616 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 617 if (!PMI) {\r
618 //\r
619 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
620 //\r
621 ZeroMem ((Cdb + 2), 4);\r
622 } else {\r
623 Cdb[8] |= 0x01;\r
624 }\r
625\r
52cd71dc 626 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 627 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
628 CommandPacket.SenseDataLength = *SenseDataLength;\r
629\r
630 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
631\r
632 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
633 *TargetStatus = CommandPacket.TargetStatus;\r
634 *SenseDataLength = CommandPacket.SenseDataLength;\r
635 *DataLength = CommandPacket.InTransferLength;\r
636\r
637 return Status;\r
638}\r
639\r
bf231ea6 640\r
a3589760 641/**\r
d5954c61 642 Execute Read(10) SCSI command on a specific SCSI target.\r
643\r
644 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
645 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
646 If Timeout is greater than zero, then the command is executed and will timeout\r
647 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
648 construct the CDB for this SCSI command.\r
649 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
650 If SenseDataLength is NULL, then ASSERT().\r
651 If HostAdapterStatus is NULL, then ASSERT().\r
652 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 653 If DataLength is NULL, then ASSERT().\r
a3589760 654\r
d5954c61 655\r
656 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
657 @param[in] Timeout The length of timeout period.\r
658 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 659 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 660 @param[out] HostAdapterStatus The status of Host Adapter.\r
661 @param[out] TargetStatus The status of the target.\r
662 @param[in, out] DataBuffer Read 10 command data.\r
ee256e2c 663 @param[in, out] DataLength The length of data buffer.\r
d5954c61 664 @param[in] StartLba The start address of LBA.\r
665 @param[in] SectorSize The sector size.\r
b91d5eca 666\r
667 @retval EFI_SUCCESS Command is executed successfully.\r
668 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
669 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
670 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
671 SCSI Command Packets already queued.\r
672 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
673 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
674 the SCSI initiator(i.e., SCSI Host Controller)\r
675 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 676\r
bf231ea6 677**/\r
a02e796b 678EFI_STATUS\r
373b5cf9 679EFIAPI\r
d35be2a4 680ScsiRead10Command (\r
d5954c61 681 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
682 IN UINT64 Timeout,\r
683 IN OUT VOID *SenseData, OPTIONAL\r
684 IN OUT UINT8 *SenseDataLength,\r
685 OUT UINT8 *HostAdapterStatus,\r
686 OUT UINT8 *TargetStatus,\r
687 IN OUT VOID *DataBuffer, OPTIONAL\r
688 IN OUT UINT32 *DataLength,\r
689 IN UINT32 StartLba,\r
690 IN UINT32 SectorSize\r
a02e796b 691 )\r
a02e796b 692{\r
693 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
694 UINT64 Lun;\r
695 UINT8 *Target;\r
696 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
697 EFI_STATUS Status;\r
52cd71dc 698 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 699\r
8069d49e
LG
700 ASSERT (SenseDataLength != NULL);\r
701 ASSERT (HostAdapterStatus != NULL);\r
702 ASSERT (TargetStatus != NULL);\r
703 ASSERT (DataLength != NULL);\r
d5954c61 704 ASSERT (ScsiIo != NULL);\r
8069d49e 705\r
a02e796b 706 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 707 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 708\r
709 CommandPacket.Timeout = Timeout;\r
710 CommandPacket.InDataBuffer = DataBuffer;\r
711 CommandPacket.SenseData = SenseData;\r
712 CommandPacket.InTransferLength= *DataLength;\r
713 CommandPacket.Cdb = Cdb;\r
714 //\r
715 // Fill Cdb for Read (10) Command\r
716 //\r
717 Target = &TargetArray[0];\r
718 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
719\r
720 Cdb[0] = EFI_SCSI_OP_READ10;\r
52cd71dc 721 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 722 Cdb[2] = (UINT8) (StartLba >> 24);\r
723 Cdb[3] = (UINT8) (StartLba >> 16);\r
724 Cdb[4] = (UINT8) (StartLba >> 8);\r
725 Cdb[5] = (UINT8) (StartLba & 0xff);\r
726 Cdb[7] = (UINT8) (SectorSize >> 8);\r
727 Cdb[8] = (UINT8) (SectorSize & 0xff);\r
728\r
52cd71dc 729 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 730 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
731 CommandPacket.SenseDataLength = *SenseDataLength;\r
732\r
733 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
734\r
735 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
736 *TargetStatus = CommandPacket.TargetStatus;\r
737 *SenseDataLength = CommandPacket.SenseDataLength;\r
738 *DataLength = CommandPacket.InTransferLength;\r
739\r
740 return Status;\r
741}\r
742\r
bf231ea6 743\r
a3589760 744/**\r
d5954c61 745 Execute Write(10) SCSI command on a specific SCSI target.\r
746\r
747 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
748 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
749 If Timeout is greater than zero, then the command is executed and will timeout after\r
750 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
751 the CDB for this SCSI command.\r
752 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
753 If SenseDataLength is NULL, then ASSERT().\r
754 If HostAdapterStatus is NULL, then ASSERT().\r
755 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 756 If DataLength is NULL, then ASSERT().\r
a3589760 757\r
d5954c61 758 @param[in] ScsiIo SCSI IO Protocol to use\r
759 @param[in] Timeout The length of timeout period.\r
760 @param[in, out] SenseData A pointer to output sense data.\r
761 @param[in, out] SenseDataLength The length of output sense data.\r
762 @param[out] HostAdapterStatus The status of Host Adapter.\r
763 @param[out] TargetStatus The status of the target.\r
764 @param[in, out] DataBuffer A pointer to a data buffer.\r
765 @param[in, out] DataLength The length of data buffer.\r
766 @param[in] StartLba The start address of LBA.\r
767 @param[in] SectorSize The sector size.\r
b91d5eca 768\r
769 @retval EFI_SUCCESS Command is executed successfully.\r
770 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
771 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
772 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
773 SCSI Command Packets already queued.\r
774 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
775 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
776 the SCSI initiator(i.e., SCSI Host Controller)\r
777 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 778\r
bf231ea6 779**/\r
a02e796b 780EFI_STATUS\r
373b5cf9 781EFIAPI\r
d35be2a4 782ScsiWrite10Command (\r
d5954c61 783 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
784 IN UINT64 Timeout,\r
785 IN OUT VOID *SenseData, OPTIONAL\r
786 IN OUT UINT8 *SenseDataLength,\r
787 OUT UINT8 *HostAdapterStatus,\r
788 OUT UINT8 *TargetStatus,\r
789 IN OUT VOID *DataBuffer, OPTIONAL\r
790 IN OUT UINT32 *DataLength,\r
791 IN UINT32 StartLba,\r
792 IN UINT32 SectorSize\r
a02e796b 793 )\r
a02e796b 794{\r
795 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
796 UINT64 Lun;\r
797 UINT8 *Target;\r
798 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
799 EFI_STATUS Status;\r
52cd71dc 800 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 801\r
8069d49e
LG
802 ASSERT (SenseDataLength != NULL);\r
803 ASSERT (HostAdapterStatus != NULL);\r
804 ASSERT (TargetStatus != NULL);\r
805 ASSERT (DataLength != NULL);\r
d5954c61 806 ASSERT (ScsiIo != NULL);\r
8069d49e 807\r
a02e796b 808 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 809 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 810\r
811 CommandPacket.Timeout = Timeout;\r
812 CommandPacket.OutDataBuffer = DataBuffer;\r
813 CommandPacket.SenseData = SenseData;\r
814 CommandPacket.OutTransferLength= *DataLength;\r
815 CommandPacket.Cdb = Cdb;\r
816 //\r
817 // Fill Cdb for Write (10) Command\r
818 //\r
819 Target = &TargetArray[0];\r
820 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
821\r
822 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
52cd71dc 823 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 824 Cdb[2] = (UINT8) (StartLba >> 24);\r
825 Cdb[3] = (UINT8) (StartLba >> 16);\r
826 Cdb[4] = (UINT8) (StartLba >> 8);\r
827 Cdb[5] = (UINT8) StartLba;\r
828 Cdb[7] = (UINT8) (SectorSize >> 8);\r
829 Cdb[8] = (UINT8) SectorSize;\r
830\r
52cd71dc 831 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 832 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
833 CommandPacket.SenseDataLength = *SenseDataLength;\r
834\r
835 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
836\r
837 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
838 *TargetStatus = CommandPacket.TargetStatus;\r
839 *SenseDataLength = CommandPacket.SenseDataLength;\r
ba7e162e 840 *DataLength = CommandPacket.OutTransferLength;\r
a02e796b 841\r
842 return Status;\r
843}\r
373b5cf9 844\r