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