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