]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
MdePkg: UefiScsiLib: do not encode LUN in CDB for READ and WRITE
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
CommitLineData
bf231ea6
A
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
b8a62661 4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
19388d29 5 This program and the accompanying materials \r
bf231ea6
A
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
2fc59a00 8 http://opensource.org/licenses/bsd-license.php. \r
bf231ea6
A
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
3e0c79b5 17#include <Library/BaseLib.h>\r
306431f7 18#include <Library/DebugLib.h>\r
172ea7c7 19#include <Library/UefiScsiLib.h>\r
a02e796b 20#include <Library/BaseMemoryLib.h>\r
d5954c61 21 \r
a3589760 22#include <IndustryStandard/Scsi.h>\r
d5954c61 23 \r
24 \r
25 //\r
26 // Max bytes needed to represent ID of a SCSI device\r
27 //\r
dfc5aca1 28#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
d5954c61 29 \r
30 //\r
31 // bit5..7 are for Logical unit number\r
32 // 11100000b (0xe0)\r
33 //\r
52cd71dc 34#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
d5954c61 35 \r
36 //\r
a24faca3 37 // Scsi Command Length\r
d5954c61 38 //\r
a24faca3 39#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
40#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
41#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10\r
bf231ea6 42\r
b91d5eca 43\r
b91d5eca 44\r
d5954c61 45/**\r
46 Execute Test Unit Ready SCSI command on a specific SCSI target.\r
b91d5eca 47\r
d5954c61 48 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
49 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
50 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
51 If ScsiIo is NULL, then ASSERT().\r
52 If SenseDataLength is NULL, then ASSERT().\r
52cd71dc
LG
53 If HostAdapterStatus is NULL, then ASSERT().\r
54 If TargetStatus is NULL, then ASSERT().\r
a3589760 55\r
d5954c61 56\r
57 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
58 for the specific SCSI target.\r
59 @param[in] Timeout The timeout in 100 ns units to use for the execution\r
60 of this SCSI Request Packet. A Timeout value of\r
61 zero means that this function will wait indefinitely\r
62 for the SCSI Request Packet to execute. If Timeout\r
63 is greater than zero, then this function will return\r
64 EFI_TIMEOUT if the time required to execute the SCSI\r
65 Request Packet is greater than Timeout.\r
66 @param[in, out] SenseData A pointer to sense data that was generated by\r
67 the execution of the SCSI Request Packet. This\r
68 buffer must be allocated by the caller.\r
69 If SenseDataLength is 0, then this parameter is\r
70 optional and may be NULL.\r
71 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
9ccbe812 72 the SenseData buffer. On output, a pointer to\r
d5954c61 73 the number of bytes written to the SenseData buffer. \r
74 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
75 the SCSI bus containing the SCSI target specified by\r
76 ScsiIo when the SCSI Request Packet was executed.\r
77 See the EFI SCSI I/O Protocol in the UEFI Specification\r
78 for details on the possible return values.\r
79 @param[out] TargetStatus The status returned by the SCSI target specified\r
9ccbe812 80 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 81 on the SCSI Host Controller. See the EFI SCSI I/O\r
82 Protocol in the UEFI Specification for details on\r
83 the possible return values. \r
84\r
85 @retval EFI_SUCCESS The command was executed successfully.\r
86 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
87 and SenseData in that order for additional status\r
88 information.\r
89 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
90 there are too many SCSI Command Packets already\r
91 queued. The SCSI Request Packet was not sent, so\r
92 no additional status information is available.\r
93 The caller may retry again later.\r
94 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
95 SCSI Request Packet. See HostAdapterStatus,\r
96 TargetStatus, SenseDataLength, and SenseData in that\r
97 order for additional status information.\r
98 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
99 is not supported by the SCSI initiator(i.e., SCSI\r
100 Host Controller). The SCSI Request Packet was not\r
101 sent, so no additional status information is available.\r
102 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
103 Packet to execute. See HostAdapterStatus, TargetStatus,\r
104 SenseDataLength, and SenseData in that order for\r
105 additional status information.\r
a3589760 106\r
bf231ea6 107**/\r
a02e796b 108EFI_STATUS\r
373b5cf9 109EFIAPI\r
d35be2a4 110ScsiTestUnitReadyCommand (\r
d5954c61 111 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
112 IN UINT64 Timeout,\r
113 IN OUT VOID *SenseData, OPTIONAL\r
114 IN OUT UINT8 *SenseDataLength,\r
115 OUT UINT8 *HostAdapterStatus,\r
116 OUT UINT8 *TargetStatus\r
a02e796b 117 )\r
a02e796b 118{\r
119 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 120 UINT64 Lun;\r
121 UINT8 *Target;\r
122 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 123 EFI_STATUS Status;\r
52cd71dc 124 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 125\r
8069d49e
LG
126 ASSERT (SenseDataLength != NULL);\r
127 ASSERT (HostAdapterStatus != NULL);\r
128 ASSERT (TargetStatus != NULL);\r
d5954c61 129 ASSERT (ScsiIo != NULL);\r
a02e796b 130\r
131 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 132 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 133\r
134 CommandPacket.Timeout = Timeout;\r
135 CommandPacket.InDataBuffer = NULL;\r
136 CommandPacket.InTransferLength= 0;\r
137 CommandPacket.OutDataBuffer = NULL;\r
138 CommandPacket.OutTransferLength= 0;\r
139 CommandPacket.SenseData = SenseData;\r
140 CommandPacket.Cdb = Cdb;\r
141 //\r
142 // Fill Cdb for Test Unit Ready Command\r
143 //\r
6b3ecf5c 144 Target = &TargetArray[0];\r
145 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
146\r
a02e796b 147 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
3e0c79b5 148 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
52cd71dc 149 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 150 CommandPacket.SenseDataLength = *SenseDataLength;\r
151\r
152 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
153\r
154 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
155 *TargetStatus = CommandPacket.TargetStatus;\r
156 *SenseDataLength = CommandPacket.SenseDataLength;\r
157\r
158 return Status;\r
159}\r
160\r
bf231ea6 161\r
a3589760 162/**\r
d5954c61 163 Execute Inquiry SCSI command on a specific SCSI target.\r
b91d5eca 164\r
d5954c61 165 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
166 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
167 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
168 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
169 If SenseDataLength is NULL, then ASSERT().\r
170 If HostAdapterStatus is NULL, then ASSERT().\r
171 If TargetStatus is NULL, then ASSERT().\r
172 If InquiryDataLength is NULL, then ASSERT().\r
a3589760 173\r
d5954c61 174 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
175 for the specific SCSI target.\r
176 @param[in] Timeout The timeout in 100 ns units to use for the\r
177 execution of this SCSI Request Packet. A Timeout\r
178 value of zero means that this function will wait\r
179 indefinitely for the SCSI Request Packet to execute.\r
180 If Timeout is greater than zero, then this function\r
181 will return EFI_TIMEOUT if the time required to\r
182 execute the SCSI Request Packet is greater than Timeout.\r
183 @param[in, out] SenseData A pointer to sense data that was generated\r
184 by the execution of the SCSI Request Packet.\r
185 This buffer must be allocated by the caller.\r
186 If SenseDataLength is 0, then this parameter\r
187 is optional and may be NULL.\r
188 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
189 On output, the number of bytes written to the SenseData buffer. \r
190 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
191 produces the SCSI bus containing the SCSI\r
192 target specified by ScsiIo when the SCSI\r
193 Request Packet was executed. See the EFI\r
194 SCSI I/O Protocol in the UEFI Specification\r
195 for details on the possible return values.\r
196 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 197 by ScsiIo when the SCSI Request Packet was\r
d5954c61 198 executed on the SCSI Host Controller.\r
199 See the EFI SCSI I/O Protocol in the UEFI\r
200 Specification for details on the possible\r
201 return values. \r
202 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
203 by the execution of the SCSI Request Packet.\r
204 This buffer must be allocated by the caller.\r
205 If InquiryDataLength is 0, then this parameter\r
206 is optional and may be NULL. \r
207 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
208 of the InquiryDataBuffer buffer.\r
209 On output, a pointer to the number of bytes\r
210 written to the InquiryDataBuffer buffer.\r
211 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
b8a62661 212 data for the PageCode is returned in InquiryDataBuffer.\r
d5954c61 213 If FALSE, then the standard inquiry data is\r
b8a62661
RN
214 returned in InquiryDataBuffer and PageCode is ignored.\r
215 @param[in] PageCode The page code of the vital product data.\r
216 It's ignored if EnableVitalProductData is FALSE.\r
d5954c61 217\r
58380e9c 218 @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,\r
d5954c61 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
b8a62661 244ScsiInquiryCommandEx (\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
b8a62661
RN
253 IN BOOLEAN EnableVitalProductData,\r
254 IN UINT8 PageCode\r
a02e796b 255 )\r
a02e796b 256{\r
257 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 258 UINT64 Lun;\r
259 UINT8 *Target;\r
260 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 261 EFI_STATUS Status;\r
52cd71dc 262 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 263\r
8069d49e
LG
264 ASSERT (SenseDataLength != NULL);\r
265 ASSERT (HostAdapterStatus != NULL);\r
266 ASSERT (TargetStatus != NULL);\r
267 ASSERT (InquiryDataLength != NULL);\r
d5954c61 268 ASSERT (ScsiIo != NULL);\r
8069d49e 269\r
a02e796b 270 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 271 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 272\r
273 CommandPacket.Timeout = Timeout;\r
274 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
275 CommandPacket.InTransferLength= *InquiryDataLength;\r
276 CommandPacket.SenseData = SenseData;\r
277 CommandPacket.SenseDataLength = *SenseDataLength;\r
278 CommandPacket.Cdb = Cdb;\r
279\r
6b3ecf5c 280 Target = &TargetArray[0];\r
281 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
282\r
a02e796b 283 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
3e0c79b5 284 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 285 if (EnableVitalProductData) {\r
286 Cdb[1] |= 0x01;\r
b8a62661 287 Cdb[2] = PageCode;\r
a02e796b 288 }\r
289\r
290 if (*InquiryDataLength > 0xff) {\r
291 *InquiryDataLength = 0xff;\r
292 }\r
293\r
294 Cdb[4] = (UINT8) (*InquiryDataLength);\r
52cd71dc 295 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 296 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
297\r
298 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
299\r
300 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
301 *TargetStatus = CommandPacket.TargetStatus;\r
302 *SenseDataLength = CommandPacket.SenseDataLength;\r
303 *InquiryDataLength = CommandPacket.InTransferLength;\r
304\r
305 return Status;\r
306}\r
307\r
bf231ea6 308\r
b8a62661
RN
309/**\r
310 Execute Inquiry SCSI command on a specific SCSI target.\r
311\r
312 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
313 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
314 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
315 If ScsiIo is NULL, then ASSERT().\r
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 InquiryDataLength is NULL, then ASSERT().\r
320\r
321 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
322 for the specific SCSI target.\r
323 @param[in] Timeout The timeout in 100 ns units to use for the\r
324 execution of this SCSI Request Packet. A Timeout\r
325 value of zero means that this function will wait\r
326 indefinitely for the SCSI Request Packet to execute.\r
327 If Timeout is greater than zero, then this function\r
328 will return EFI_TIMEOUT if the time required to\r
329 execute the SCSI Request Packet is greater than Timeout.\r
330 @param[in, out] SenseData A pointer to sense data that was generated\r
331 by the execution of the SCSI Request Packet.\r
332 This buffer must be allocated by the caller.\r
333 If SenseDataLength is 0, then this parameter\r
334 is optional and may be NULL.\r
335 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
336 On output, the number of bytes written to the SenseData buffer. \r
337 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
338 produces the SCSI bus containing the SCSI\r
339 target specified by ScsiIo when the SCSI\r
340 Request Packet was executed. See the EFI\r
341 SCSI I/O Protocol in the UEFI Specification\r
342 for details on the possible return values.\r
343 @param[out] TargetStatus The status returned by the SCSI target specified\r
344 by ScsiIo when the SCSI Request Packet was\r
345 executed on the SCSI Host Controller.\r
346 See the EFI SCSI I/O Protocol in the UEFI\r
347 Specification for details on the possible\r
348 return values. \r
349 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
350 by the execution of the SCSI Request Packet.\r
351 This buffer must be allocated by the caller.\r
352 If InquiryDataLength is 0, then this parameter\r
353 is optional and may be NULL. \r
354 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
355 of the InquiryDataBuffer buffer.\r
356 On output, a pointer to the number of bytes\r
357 written to the InquiryDataBuffer buffer.\r
358 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
359 data is returned in InquiryDataBuffer.\r
360 If FALSE, then the standard inquiry data is\r
361 returned in InquiryDataBuffer. \r
362\r
363 @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,\r
364 TargetStatus, SenseDataLength, and SenseData in that order\r
365 for additional status information.\r
366 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
367 InquiryDataBuffer could not be transferred. The actual\r
368 number of bytes transferred is returned in InquiryDataLength.\r
369 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
370 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 again later.\r
373 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
374 Request Packet. See HostAdapterStatus, TargetStatus,\r
375 SenseDataLength, and SenseData in that order for additional\r
376 status information.\r
377 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
378 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
379 The SCSI Request Packet was not sent, so no additional\r
380 status information is available.\r
381 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
382 Packet to execute. See HostAdapterStatus, TargetStatus,\r
383 SenseDataLength, and SenseData in that order for\r
384 additional status information.\r
385\r
386**/\r
387EFI_STATUS\r
388EFIAPI\r
389ScsiInquiryCommand (\r
390 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
391 IN UINT64 Timeout,\r
392 IN OUT VOID *SenseData, OPTIONAL\r
393 IN OUT UINT8 *SenseDataLength,\r
394 OUT UINT8 *HostAdapterStatus,\r
395 OUT UINT8 *TargetStatus,\r
396 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
397 IN OUT UINT32 *InquiryDataLength,\r
398 IN BOOLEAN EnableVitalProductData\r
399 )\r
400{\r
401 return ScsiInquiryCommandEx (\r
402 ScsiIo,\r
403 Timeout,\r
404 SenseData,\r
405 SenseDataLength,\r
406 HostAdapterStatus,\r
407 TargetStatus,\r
408 InquiryDataBuffer,\r
409 InquiryDataLength,\r
410 EnableVitalProductData,\r
411 0\r
412 );\r
413}\r
414\r
a3589760 415/**\r
d5954c61 416 Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
417\r
418 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
419 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
420 If Timeout is greater than zero, then the command is executed and will timeout\r
421 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
422 are used to construct the CDB for this SCSI command.\r
423 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
424 If SenseDataLength is NULL, then ASSERT().\r
425 If HostAdapterStatus is NULL, then ASSERT().\r
426 If TargetStatus is NULL, then ASSERT().\r
427 If DataLength is NULL, then ASSERT().\r
a3589760 428\r
d5954c61 429\r
430 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
431 for the specific SCSI target.\r
432 @param[in] Timeout The timeout in 100 ns units to use for the\r
433 execution of this SCSI Request Packet. A Timeout\r
434 value of zero means that this function will wait\r
435 indefinitely for the SCSI Request Packet to execute.\r
436 If Timeout is greater than zero, then this function\r
437 will return EFI_TIMEOUT if the time required to\r
438 execute the SCSI Request Packet is greater than Timeout.\r
6089ba62 439 @param[in, out] SenseData A pointer to sense data that was generated\r
d5954c61 440 by the execution of the SCSI Request Packet.\r
441 This buffer must be allocated by the caller.\r
442 If SenseDataLength is 0, then this parameter\r
443 is optional and may be NULL.\r
6089ba62 444 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
d5954c61 445 On output, the number of bytes written to the SenseData buffer. \r
446 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
447 produces the SCSI bus containing the SCSI target\r
448 specified by ScsiIo when the SCSI Request Packet\r
449 was executed. See the EFI SCSI I/O Protocol in the\r
450 UEFI Specification for details on the possible\r
451 return values.\r
452 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 453 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 454 on the SCSI Host Controller. See the EFI SCSI\r
455 I/O Protocol in the UEFI Specification for details\r
456 on the possible return values.\r
457 @param[in, out] DataBuffer A pointer to data that was generated by the\r
458 execution of the SCSI Request Packet. This\r
459 buffer must be allocated by the caller. If\r
460 DataLength is 0, then this parameter is optional\r
461 and may be NULL. \r
462 @param[in, out] DataLength On input, a pointer to the length in bytes of\r
463 the DataBuffer buffer. On output, a pointer\r
464 to the number of bytes written to the DataBuffer\r
465 buffer. \r
466 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
467 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. \r
468 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. \r
469\r
58380e9c 470 @retval EFI_SUCCESS The command executed successfully.\r
d5954c61 471 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
472 and SenseData in that order for additional status information.\r
473 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
474 entire DataBuffer could not be transferred.\r
bf231ea6 475 The actual number of bytes transferred is returned\r
d5954c61 476 in DataLength.\r
477 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
478 there are too many SCSI Command Packets already queued.\r
479 The SCSI Request Packet was not sent, so no additional\r
480 status information is available. The caller may retry\r
481 again later.\r
482 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
483 SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
484 SenseDataLength, and SenseData in that order for\r
485 additional status information.\r
bf231ea6 486 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
d5954c61 487 is not supported by the SCSI initiator(i.e., SCSI\r
488 Host Controller). The SCSI Request Packet was not\r
489 sent, so no additional status information is available.\r
490 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
491 Request Packet to execute. See HostAdapterStatus,\r
492 TargetStatus, SenseDataLength, and SenseData in that\r
493 order for additional status information.\r
a3589760 494\r
bf231ea6 495**/\r
a02e796b 496EFI_STATUS\r
373b5cf9 497EFIAPI\r
d35be2a4 498ScsiModeSense10Command (\r
d5954c61 499 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
500 IN UINT64 Timeout,\r
501 IN OUT VOID *SenseData, OPTIONAL\r
502 IN OUT UINT8 *SenseDataLength,\r
503 OUT UINT8 *HostAdapterStatus,\r
504 OUT UINT8 *TargetStatus,\r
505 IN OUT VOID *DataBuffer, OPTIONAL\r
506 IN OUT UINT32 *DataLength,\r
507 IN UINT8 DBDField, OPTIONAL\r
508 IN UINT8 PageControl,\r
509 IN UINT8 PageCode\r
a02e796b 510 )\r
a02e796b 511{\r
512 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 513 UINT64 Lun;\r
514 UINT8 *Target;\r
515 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 516 EFI_STATUS Status;\r
52cd71dc 517 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 518\r
8069d49e
LG
519 ASSERT (SenseDataLength != NULL);\r
520 ASSERT (HostAdapterStatus != NULL);\r
521 ASSERT (TargetStatus != NULL);\r
522 ASSERT (DataLength != NULL);\r
d5954c61 523 ASSERT (ScsiIo != NULL);\r
8069d49e 524\r
a02e796b 525 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 526 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 527\r
528 CommandPacket.Timeout = Timeout;\r
529 CommandPacket.InDataBuffer = DataBuffer;\r
530 CommandPacket.SenseData = SenseData;\r
531 CommandPacket.InTransferLength= *DataLength;\r
532 CommandPacket.Cdb = Cdb;\r
533 //\r
534 // Fill Cdb for Mode Sense (10) Command\r
535 //\r
6b3ecf5c 536 Target = &TargetArray[0];\r
537 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
538\r
a02e796b 539 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
52cd71dc
LG
540 //\r
541 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
542 //\r
3e0c79b5 543 Cdb[1] = (UINT8) ((LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));\r
52cd71dc
LG
544 //\r
545 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
546 //\r
6b3ecf5c 547 Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));\r
a02e796b 548 Cdb[7] = (UINT8) (*DataLength >> 8);\r
549 Cdb[8] = (UINT8) (*DataLength);\r
550\r
52cd71dc 551 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 552 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
553 CommandPacket.SenseDataLength = *SenseDataLength;\r
554\r
555 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
556\r
557 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
558 *TargetStatus = CommandPacket.TargetStatus;\r
559 *SenseDataLength = CommandPacket.SenseDataLength;\r
560 *DataLength = CommandPacket.InTransferLength;\r
561\r
562 return Status;\r
563}\r
564\r
bf231ea6 565\r
a3589760 566/**\r
d5954c61 567 Execute Request Sense SCSI command on a specific SCSI target.\r
b91d5eca 568\r
d5954c61 569 Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
570 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
571 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
572 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
573 If SenseDataLength is NULL, then ASSERT().\r
574 If HostAdapterStatus is NULL, then ASSERT().\r
575 If TargetStatus is NULL, then ASSERT().\r
a3589760 576\r
b91d5eca 577 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
578 @param[in] Timeout The length of timeout period.\r
d5954c61 579 @param[in, out] SenseData A pointer to output sense data.\r
580 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 581 @param[out] HostAdapterStatus The status of Host Adapter.\r
582 @param[out] TargetStatus The status of the target.\r
583\r
58380e9c 584 @retval EFI_SUCCESS The command executed successfully.\r
b91d5eca 585 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
586 too many SCSI Command Packets already queued.\r
587 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
588 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
589 the SCSI initiator(i.e., SCSI Host Controller)\r
590 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 591\r
bf231ea6 592**/\r
a02e796b 593EFI_STATUS\r
373b5cf9 594EFIAPI\r
d35be2a4 595ScsiRequestSenseCommand (\r
d5954c61 596 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
597 IN UINT64 Timeout,\r
598 IN OUT VOID *SenseData, OPTIONAL\r
599 IN OUT UINT8 *SenseDataLength,\r
600 OUT UINT8 *HostAdapterStatus,\r
601 OUT UINT8 *TargetStatus\r
a02e796b 602 )\r
a02e796b 603{\r
604 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 605 UINT64 Lun;\r
606 UINT8 *Target;\r
607 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 608 EFI_STATUS Status;\r
52cd71dc 609 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 610\r
8069d49e
LG
611 ASSERT (SenseDataLength != NULL);\r
612 ASSERT (HostAdapterStatus != NULL);\r
613 ASSERT (TargetStatus != NULL);\r
d5954c61 614 ASSERT (ScsiIo != NULL);\r
8069d49e 615\r
a02e796b 616 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 617 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 618\r
619 CommandPacket.Timeout = Timeout;\r
620 CommandPacket.InDataBuffer = SenseData;\r
621 CommandPacket.SenseData = NULL;\r
622 CommandPacket.InTransferLength= *SenseDataLength;\r
623 CommandPacket.Cdb = Cdb;\r
624 //\r
625 // Fill Cdb for Request Sense Command\r
626 //\r
6b3ecf5c 627 Target = &TargetArray[0];\r
628 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
629\r
a02e796b 630 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
3e0c79b5 631 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 632 Cdb[4] = (UINT8) (*SenseDataLength);\r
633\r
52cd71dc 634 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 635 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
636 CommandPacket.SenseDataLength = 0;\r
637\r
638 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
639\r
640 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
641 *TargetStatus = CommandPacket.TargetStatus;\r
642 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
643\r
644 return Status;\r
645}\r
646\r
bf231ea6 647\r
a3589760 648/**\r
d5954c61 649 Execute Read Capacity SCSI command on a specific SCSI target.\r
b91d5eca 650\r
d5954c61 651 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
652 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
653 If Timeout is greater than zero, then the command is executed and will timeout after\r
51969ecb 654 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
d5954c61 655 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
656 If SenseDataLength is NULL, then ASSERT().\r
657 If HostAdapterStatus is NULL, then ASSERT().\r
658 If TargetStatus is NULL, then ASSERT().\r
659 If DataLength is NULL, then ASSERT().\r
bf231ea6 660\r
d5954c61 661 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
662 @param[in] Timeout The length of timeout period.\r
663 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 664 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 665 @param[out] HostAdapterStatus The status of Host Adapter.\r
666 @param[out] TargetStatus The status of the target.\r
667 @param[in, out] DataBuffer A pointer to a data buffer.\r
ee256e2c 668 @param[in, out] DataLength The length of data buffer.\r
58380e9c 669 @param[in] Pmi A partial medium indicator.\r
b91d5eca 670\r
58380e9c 671 @retval EFI_SUCCESS The command executed successfully.\r
6089ba62 672 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
673 DataBuffer could not be transferred. The actual\r
674 number of bytes transferred is returned in DataLength.\r
675 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
676 there are too many SCSI Command Packets already queued.\r
677 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
678 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
679 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
680 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 681\r
bf231ea6 682**/\r
a02e796b 683EFI_STATUS\r
373b5cf9 684EFIAPI\r
d35be2a4 685ScsiReadCapacityCommand (\r
d5954c61 686 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
687 IN UINT64 Timeout,\r
688 IN OUT VOID *SenseData, OPTIONAL\r
689 IN OUT UINT8 *SenseDataLength,\r
690 OUT UINT8 *HostAdapterStatus,\r
691 OUT UINT8 *TargetStatus,\r
692 IN OUT VOID *DataBuffer, OPTIONAL\r
693 IN OUT UINT32 *DataLength,\r
51969ecb 694 IN BOOLEAN Pmi\r
a02e796b 695 )\r
a02e796b 696{\r
697 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 698 UINT64 Lun;\r
699 UINT8 *Target;\r
700 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 701 EFI_STATUS Status;\r
52cd71dc 702 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 703\r
8069d49e
LG
704 ASSERT (SenseDataLength != NULL);\r
705 ASSERT (HostAdapterStatus != NULL);\r
706 ASSERT (TargetStatus != NULL);\r
707 ASSERT (DataLength != NULL);\r
d5954c61 708 ASSERT (ScsiIo != NULL);\r
8069d49e 709\r
a02e796b 710 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 711 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 712\r
713 CommandPacket.Timeout = Timeout;\r
714 CommandPacket.InDataBuffer = DataBuffer;\r
715 CommandPacket.SenseData = SenseData;\r
716 CommandPacket.InTransferLength= *DataLength;\r
717 CommandPacket.Cdb = Cdb;\r
718 //\r
719 // Fill Cdb for Read Capacity Command\r
720 //\r
6b3ecf5c 721 Target = &TargetArray[0];\r
722 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
723\r
a02e796b 724 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
3e0c79b5 725 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
51969ecb 726 if (!Pmi) {\r
a02e796b 727 //\r
51969ecb 728 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
a02e796b 729 //\r
730 ZeroMem ((Cdb + 2), 4);\r
731 } else {\r
732 Cdb[8] |= 0x01;\r
733 }\r
734\r
52cd71dc 735 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 736 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
737 CommandPacket.SenseDataLength = *SenseDataLength;\r
738\r
739 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
740\r
741 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
742 *TargetStatus = CommandPacket.TargetStatus;\r
743 *SenseDataLength = CommandPacket.SenseDataLength;\r
744 *DataLength = CommandPacket.InTransferLength;\r
745\r
746 return Status;\r
747}\r
748\r
bf231ea6 749\r
ccb491c8 750/**\r
5e11e7c6 751 Execute Read Capacity SCSI 16 command on a specific SCSI target.\r
752\r
753 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.\r
754 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
755 If Timeout is greater than zero, then the command is executed and will timeout after\r
756 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
757 If ScsiIo is NULL, then ASSERT().\r
758 If SenseDataLength is NULL, then ASSERT().\r
759 If HostAdapterStatus is NULL, then ASSERT().\r
760 If TargetStatus is NULL, then ASSERT().\r
761 If DataLength is NULL, then ASSERT().\r
762\r
763 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
764 @param[in] Timeout The length of timeout period.\r
765 @param[in, out] SenseData A pointer to output sense data.\r
766 @param[in, out] SenseDataLength The length of output sense data.\r
767 @param[out] HostAdapterStatus The status of Host Adapter.\r
768 @param[out] TargetStatus The status of the target.\r
769 @param[in, out] DataBuffer A pointer to a data buffer.\r
770 @param[in, out] DataLength The length of data buffer.\r
771 @param[in] Pmi Partial medium indicator.\r
772\r
58380e9c 773 @retval EFI_SUCCESS The command executed successfully.\r
5e11e7c6 774 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
775 DataBuffer could not be transferred. The actual\r
776 number of bytes transferred is returned in DataLength.\r
777 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
778 there are too many SCSI Command Packets already queued.\r
779 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
780 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
781 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
782 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
ccb491c8 783\r
784**/\r
ccb491c8 785EFI_STATUS\r
786EFIAPI\r
787ScsiReadCapacity16Command (\r
f158ee67 788 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
789 IN UINT64 Timeout,\r
790 IN OUT VOID *SenseData, OPTIONAL\r
791 IN OUT UINT8 *SenseDataLength,\r
792 OUT UINT8 *HostAdapterStatus,\r
793 OUT UINT8 *TargetStatus,\r
794 IN OUT VOID *DataBuffer, OPTIONAL\r
795 IN OUT UINT32 *DataLength,\r
796 IN BOOLEAN Pmi\r
ccb491c8 797 )\r
798{\r
799 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 800 UINT64 Lun;\r
801 UINT8 *Target;\r
802 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
ccb491c8 803 EFI_STATUS Status;\r
804 UINT8 Cdb[16];\r
805\r
5fe71b5f 806 ASSERT (SenseDataLength != NULL);\r
807 ASSERT (HostAdapterStatus != NULL);\r
808 ASSERT (TargetStatus != NULL);\r
809 ASSERT (DataLength != NULL);\r
810 ASSERT (ScsiIo != NULL);\r
811\r
ccb491c8 812 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
813 ZeroMem (Cdb, 16);\r
814\r
815 CommandPacket.Timeout = Timeout;\r
816 CommandPacket.InDataBuffer = DataBuffer;\r
817 CommandPacket.SenseData = SenseData;\r
818 CommandPacket.InTransferLength= *DataLength;\r
819 CommandPacket.Cdb = Cdb;\r
820 //\r
821 // Fill Cdb for Read Capacity Command\r
822 //\r
6b3ecf5c 823 Target = &TargetArray[0];\r
824 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
825\r
ccb491c8 826 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
827 Cdb[1] = 0x10;\r
51969ecb 828 if (!Pmi) {\r
ccb491c8 829 //\r
51969ecb 830 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
ccb491c8 831 //\r
832 ZeroMem ((Cdb + 2), 8);\r
833 } else {\r
834 Cdb[14] |= 0x01;\r
835 }\r
836\r
837 Cdb[13] = 0x20;\r
838 CommandPacket.CdbLength = 16;\r
839 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
840 CommandPacket.SenseDataLength = *SenseDataLength;\r
841\r
842 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
843\r
844 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
845 *TargetStatus = CommandPacket.TargetStatus;\r
846 *SenseDataLength = CommandPacket.SenseDataLength;\r
847 *DataLength = CommandPacket.InTransferLength;\r
848\r
849 return Status;\r
850}\r
851\r
852\r
a3589760 853/**\r
d5954c61 854 Execute Read(10) SCSI command on a specific SCSI target.\r
855\r
856 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
857 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
858 If Timeout is greater than zero, then the command is executed and will timeout\r
859 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
860 construct the CDB for this SCSI command.\r
861 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
862 If SenseDataLength is NULL, then ASSERT().\r
863 If HostAdapterStatus is NULL, then ASSERT().\r
864 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 865 If DataLength is NULL, then ASSERT().\r
a3589760 866\r
d5954c61 867\r
868 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
869 @param[in] Timeout The length of timeout period.\r
870 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 871 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 872 @param[out] HostAdapterStatus The status of Host Adapter.\r
873 @param[out] TargetStatus The status of the target.\r
874 @param[in, out] DataBuffer Read 10 command data.\r
ee256e2c 875 @param[in, out] DataLength The length of data buffer.\r
d5954c61 876 @param[in] StartLba The start address of LBA.\r
b95eb5e0 877 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
b91d5eca 878\r
58380e9c 879 @retval EFI_SUCCESS The command is executed successfully.\r
6089ba62 880 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
881 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
882 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
883 SCSI Command Packets already queued.\r
884 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
885 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
886 the SCSI initiator(i.e., SCSI Host Controller)\r
887 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 888\r
bf231ea6 889**/\r
a02e796b 890EFI_STATUS\r
373b5cf9 891EFIAPI\r
d35be2a4 892ScsiRead10Command (\r
d5954c61 893 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
894 IN UINT64 Timeout,\r
895 IN OUT VOID *SenseData, OPTIONAL\r
896 IN OUT UINT8 *SenseDataLength,\r
897 OUT UINT8 *HostAdapterStatus,\r
898 OUT UINT8 *TargetStatus,\r
899 IN OUT VOID *DataBuffer, OPTIONAL\r
900 IN OUT UINT32 *DataLength,\r
901 IN UINT32 StartLba,\r
902 IN UINT32 SectorSize\r
a02e796b 903 )\r
a02e796b 904{\r
905 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 906 EFI_STATUS Status;\r
52cd71dc 907 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 908\r
8069d49e
LG
909 ASSERT (SenseDataLength != NULL);\r
910 ASSERT (HostAdapterStatus != NULL);\r
911 ASSERT (TargetStatus != NULL);\r
912 ASSERT (DataLength != NULL);\r
d5954c61 913 ASSERT (ScsiIo != NULL);\r
8069d49e 914\r
a02e796b 915 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 916 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 917\r
918 CommandPacket.Timeout = Timeout;\r
919 CommandPacket.InDataBuffer = DataBuffer;\r
920 CommandPacket.SenseData = SenseData;\r
921 CommandPacket.InTransferLength= *DataLength;\r
922 CommandPacket.Cdb = Cdb;\r
923 //\r
924 // Fill Cdb for Read (10) Command\r
925 //\r
a02e796b 926 Cdb[0] = EFI_SCSI_OP_READ10;\r
a24faca3 927 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
928 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 929\r
52cd71dc 930 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 931 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
932 CommandPacket.SenseDataLength = *SenseDataLength;\r
933\r
934 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
935\r
936 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
937 *TargetStatus = CommandPacket.TargetStatus;\r
938 *SenseDataLength = CommandPacket.SenseDataLength;\r
939 *DataLength = CommandPacket.InTransferLength;\r
940\r
941 return Status;\r
942}\r
943\r
bf231ea6 944\r
a3589760 945/**\r
d5954c61 946 Execute Write(10) SCSI command on a specific SCSI target.\r
947\r
948 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
949 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
950 If Timeout is greater than zero, then the command is executed and will timeout after\r
951 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
952 the CDB for this SCSI command.\r
953 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
954 If SenseDataLength is NULL, then ASSERT().\r
955 If HostAdapterStatus is NULL, then ASSERT().\r
956 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 957 If DataLength is NULL, then ASSERT().\r
a3589760 958\r
d5954c61 959 @param[in] ScsiIo SCSI IO Protocol to use\r
960 @param[in] Timeout The length of timeout period.\r
961 @param[in, out] SenseData A pointer to output sense data.\r
6089ba62 962 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 963 @param[out] HostAdapterStatus The status of Host Adapter.\r
964 @param[out] TargetStatus The status of the target.\r
965 @param[in, out] DataBuffer A pointer to a data buffer.\r
6089ba62 966 @param[in, out] DataLength The length of data buffer.\r
d5954c61 967 @param[in] StartLba The start address of LBA.\r
b95eb5e0 968 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
b91d5eca 969\r
58380e9c 970 @retval EFI_SUCCESS The command executed successfully.\r
6089ba62 971 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
972 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
973 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
974 SCSI Command Packets already queued.\r
975 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
976 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
977 the SCSI initiator(i.e., SCSI Host Controller)\r
978 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 979\r
bf231ea6 980**/\r
a02e796b 981EFI_STATUS\r
373b5cf9 982EFIAPI\r
d35be2a4 983ScsiWrite10Command (\r
d5954c61 984 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
985 IN UINT64 Timeout,\r
986 IN OUT VOID *SenseData, OPTIONAL\r
987 IN OUT UINT8 *SenseDataLength,\r
988 OUT UINT8 *HostAdapterStatus,\r
989 OUT UINT8 *TargetStatus,\r
990 IN OUT VOID *DataBuffer, OPTIONAL\r
991 IN OUT UINT32 *DataLength,\r
992 IN UINT32 StartLba,\r
993 IN UINT32 SectorSize\r
a02e796b 994 )\r
a02e796b 995{\r
996 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 997 EFI_STATUS Status;\r
52cd71dc 998 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 999\r
8069d49e
LG
1000 ASSERT (SenseDataLength != NULL);\r
1001 ASSERT (HostAdapterStatus != NULL);\r
1002 ASSERT (TargetStatus != NULL);\r
1003 ASSERT (DataLength != NULL);\r
d5954c61 1004 ASSERT (ScsiIo != NULL);\r
8069d49e 1005\r
a02e796b 1006 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 1007 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 1008\r
1009 CommandPacket.Timeout = Timeout;\r
1010 CommandPacket.OutDataBuffer = DataBuffer;\r
1011 CommandPacket.SenseData = SenseData;\r
1012 CommandPacket.OutTransferLength= *DataLength;\r
1013 CommandPacket.Cdb = Cdb;\r
1014 //\r
1015 // Fill Cdb for Write (10) Command\r
1016 //\r
a02e796b 1017 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
a24faca3 1018 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
1019 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 1020\r
52cd71dc 1021 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 1022 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1023 CommandPacket.SenseDataLength = *SenseDataLength;\r
1024\r
1025 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1026\r
1027 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1028 *TargetStatus = CommandPacket.TargetStatus;\r
1029 *SenseDataLength = CommandPacket.SenseDataLength;\r
ba7e162e 1030 *DataLength = CommandPacket.OutTransferLength;\r
a02e796b 1031\r
1032 return Status;\r
1033}\r
373b5cf9 1034\r
a24faca3 1035/**\r
1036 Execute Read(16) SCSI command on a specific SCSI target.\r
1037\r
1038 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
1039 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1040 If Timeout is greater than zero, then the command is executed and will timeout\r
1041 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
1042 construct the CDB for this SCSI command.\r
1043 If ScsiIo is NULL, then ASSERT().\r
1044 If SenseDataLength is NULL, then ASSERT().\r
1045 If HostAdapterStatus is NULL, then ASSERT().\r
1046 If TargetStatus is NULL, then ASSERT().\r
1047 If DataLength is NULL, then ASSERT().\r
1048\r
1049\r
1050 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
1051 @param[in] Timeout The length of timeout period.\r
1052 @param[in, out] SenseData A pointer to output sense data.\r
1053 @param[in, out] SenseDataLength The length of output sense data.\r
1054 @param[out] HostAdapterStatus The status of Host Adapter.\r
1055 @param[out] TargetStatus The status of the target.\r
1056 @param[in, out] DataBuffer Read 16 command data.\r
1057 @param[in, out] DataLength The length of data buffer.\r
1058 @param[in] StartLba The start address of LBA.\r
b95eb5e0 1059 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
a24faca3 1060\r
58380e9c 1061 @retval EFI_SUCCESS The command executed successfully.\r
a24faca3 1062 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1063 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1064 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
1065 SCSI Command Packets already queued.\r
1066 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1067 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
1068 the SCSI initiator(i.e., SCSI Host Controller)\r
1069 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1070\r
1071**/\r
1072EFI_STATUS\r
1073EFIAPI\r
1074ScsiRead16Command (\r
1075 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1076 IN UINT64 Timeout,\r
1077 IN OUT VOID *SenseData, OPTIONAL\r
1078 IN OUT UINT8 *SenseDataLength,\r
1079 OUT UINT8 *HostAdapterStatus,\r
1080 OUT UINT8 *TargetStatus,\r
1081 IN OUT VOID *DataBuffer, OPTIONAL\r
1082 IN OUT UINT32 *DataLength,\r
1083 IN UINT64 StartLba,\r
1084 IN UINT32 SectorSize\r
1085 )\r
1086{\r
1087 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a24faca3 1088 EFI_STATUS Status;\r
1089 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
1090\r
1091 ASSERT (SenseDataLength != NULL);\r
1092 ASSERT (HostAdapterStatus != NULL);\r
1093 ASSERT (TargetStatus != NULL);\r
1094 ASSERT (DataLength != NULL);\r
1095 ASSERT (ScsiIo != NULL);\r
1096\r
1097 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1098 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1099\r
1100 CommandPacket.Timeout = Timeout;\r
1101 CommandPacket.InDataBuffer = DataBuffer;\r
1102 CommandPacket.SenseData = SenseData;\r
1103 CommandPacket.InTransferLength = *DataLength;\r
1104 CommandPacket.Cdb = Cdb;\r
1105 //\r
1106 // Fill Cdb for Read (16) Command\r
1107 //\r
a24faca3 1108 Cdb[0] = EFI_SCSI_OP_READ16;\r
a24faca3 1109 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1110 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1111\r
1112 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1113 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
1114 CommandPacket.SenseDataLength = *SenseDataLength;\r
1115\r
1116 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1117\r
1118 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1119 *TargetStatus = CommandPacket.TargetStatus;\r
1120 *SenseDataLength = CommandPacket.SenseDataLength;\r
1121 *DataLength = CommandPacket.InTransferLength;\r
1122\r
1123 return Status;\r
1124}\r
1125\r
1126\r
1127/**\r
1128 Execute Write(16) SCSI command on a specific SCSI target.\r
1129\r
1130 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
1131 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1132 If Timeout is greater than zero, then the command is executed and will timeout after\r
1133 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
1134 the CDB for this SCSI command.\r
1135 If ScsiIo is NULL, then ASSERT().\r
1136 If SenseDataLength is NULL, then ASSERT().\r
1137 If HostAdapterStatus is NULL, then ASSERT().\r
1138 If TargetStatus is NULL, then ASSERT().\r
1139 If DataLength is NULL, then ASSERT().\r
1140\r
1141 @param[in] ScsiIo SCSI IO Protocol to use\r
1142 @param[in] Timeout The length of timeout period.\r
1143 @param[in, out] SenseData A pointer to output sense data.\r
1144 @param[in, out] SenseDataLength The length of output sense data.\r
1145 @param[out] HostAdapterStatus The status of Host Adapter.\r
1146 @param[out] TargetStatus The status of the target.\r
1147 @param[in, out] DataBuffer A pointer to a data buffer.\r
1148 @param[in, out] DataLength The length of data buffer.\r
1149 @param[in] StartLba The start address of LBA.\r
b95eb5e0 1150 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
a24faca3 1151\r
58380e9c 1152 @retval EFI_SUCCESS The command is executed successfully.\r
a24faca3 1153 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1154 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1155 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
1156 SCSI Command Packets already queued.\r
1157 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1158 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
1159 the SCSI initiator(i.e., SCSI Host Controller)\r
1160 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1161\r
1162**/\r
1163EFI_STATUS\r
1164EFIAPI\r
1165ScsiWrite16Command (\r
1166 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1167 IN UINT64 Timeout,\r
1168 IN OUT VOID *SenseData, OPTIONAL\r
1169 IN OUT UINT8 *SenseDataLength,\r
1170 OUT UINT8 *HostAdapterStatus,\r
1171 OUT UINT8 *TargetStatus,\r
1172 IN OUT VOID *DataBuffer, OPTIONAL\r
1173 IN OUT UINT32 *DataLength,\r
1174 IN UINT64 StartLba,\r
1175 IN UINT32 SectorSize\r
1176 )\r
1177{\r
1178 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a24faca3 1179 EFI_STATUS Status;\r
1180 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
1181\r
1182 ASSERT (SenseDataLength != NULL);\r
1183 ASSERT (HostAdapterStatus != NULL);\r
1184 ASSERT (TargetStatus != NULL);\r
1185 ASSERT (DataLength != NULL);\r
1186 ASSERT (ScsiIo != NULL);\r
1187\r
1188 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1189 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1190\r
1191 CommandPacket.Timeout = Timeout;\r
1192 CommandPacket.OutDataBuffer = DataBuffer;\r
1193 CommandPacket.SenseData = SenseData;\r
1194 CommandPacket.OutTransferLength = *DataLength;\r
1195 CommandPacket.Cdb = Cdb;\r
1196 //\r
1197 // Fill Cdb for Write (16) Command\r
1198 //\r
a24faca3 1199 Cdb[0] = EFI_SCSI_OP_WRITE16;\r
a24faca3 1200 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1201 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1202\r
1203 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1204 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1205 CommandPacket.SenseDataLength = *SenseDataLength;\r
1206\r
1207 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1208\r
1209 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1210 *TargetStatus = CommandPacket.TargetStatus;\r
1211 *SenseDataLength = CommandPacket.SenseDataLength;\r
1212 *DataLength = CommandPacket.OutTransferLength;\r
1213\r
1214 return Status;\r
1215}\r