]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
Move definition of EFI_SCSI_TARGET_MAX_BYTES from IndustryStandard in MDE Package...
[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
a02e796b 18#include <Library/ScsiLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20\r
a3589760 21#include <IndustryStandard/Scsi.h>\r
a02e796b 22\r
dfc5aca1 23//\r
24// Max bytes needed to represent ID of a SCSI device\r
25//\r
26#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
27\r
52cd71dc
LG
28//\r
29// bit5..7 are for Logical unit number\r
30// 11100000b (0xe0)\r
31//\r
32#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
33\r
34//\r
35// Scsi Command Length six or ten\r
36//\r
37#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
38#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
bf231ea6 39\r
a3589760 40/**\r
bf231ea6 41 Function test the ready status of the SCSI unit.\r
b91d5eca 42\r
43 Submit SCSI test unit ready command with SCSI request packet specified by this scsi command, TimeOut\r
44 and SenseData, then get the status of the target Scsi unit.\r
45\r
52cd71dc 46 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 47\r
52cd71dc 48 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 49\r
52cd71dc 50 If TargetStatus is NULL, then ASSERT().\r
a3589760 51\r
52 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
53 @param[in] Timeout The length of timeout period.\r
956a6dca 54 @param[in] SenseData A pointer to output sense data.\r
b91d5eca 55 @param[out] SenseDataLength The length of output sense data.\r
a3589760 56 @param[out] HostAdapterStatus The status of Host Adapter.\r
57 @param[out] TargetStatus The status of the target.\r
58\r
bf231ea6
A
59 @retval EFI_SUCCESS The status of the unit is tested successfully.\r
60 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
61 but the entire DataBuffer could not be transferred.\r
62 The actual number of bytes transferred is returned\r
63 in InTransferLength.\r
64 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
65 there are too many SCSI Command Packets already \r
66 queued.\r
67 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
68 the SCSI Request Packet.\r
b91d5eca 69 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
bf231ea6
A
70 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
71 is not supported by the SCSI initiator(i.e., SCSI \r
72 Host Controller).\r
73 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
74 Request Packet to execute.\r
a3589760 75\r
bf231ea6 76**/\r
a02e796b 77EFI_STATUS\r
373b5cf9 78EFIAPI\r
d35be2a4 79ScsiTestUnitReadyCommand (\r
a02e796b 80 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
81 IN UINT64 Timeout,\r
956a6dca 82 IN VOID *SenseData,\r
83 OUT UINT8 *SenseDataLength,\r
a02e796b 84 OUT UINT8 *HostAdapterStatus,\r
85 OUT UINT8 *TargetStatus\r
86 )\r
a02e796b 87{\r
88 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
89 UINT64 Lun;\r
90 UINT8 *Target;\r
91 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
92 EFI_STATUS Status;\r
52cd71dc 93 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 94\r
8069d49e
LG
95 ASSERT (SenseDataLength != NULL);\r
96 ASSERT (HostAdapterStatus != NULL);\r
97 ASSERT (TargetStatus != NULL);\r
98 \r
99 if (ScsiIo == NULL) {\r
100 return EFI_INVALID_PARAMETER;\r
101 }\r
a02e796b 102\r
103 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 104 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 105\r
106 CommandPacket.Timeout = Timeout;\r
107 CommandPacket.InDataBuffer = NULL;\r
108 CommandPacket.InTransferLength= 0;\r
109 CommandPacket.OutDataBuffer = NULL;\r
110 CommandPacket.OutTransferLength= 0;\r
111 CommandPacket.SenseData = SenseData;\r
112 CommandPacket.Cdb = Cdb;\r
113 //\r
114 // Fill Cdb for Test Unit Ready Command\r
115 //\r
116 Target = &TargetArray[0];\r
117 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
118\r
119 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
52cd71dc
LG
120 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
121 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 122 CommandPacket.SenseDataLength = *SenseDataLength;\r
123\r
124 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
125\r
126 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
127 *TargetStatus = CommandPacket.TargetStatus;\r
128 *SenseDataLength = CommandPacket.SenseDataLength;\r
129\r
130 return Status;\r
131}\r
132\r
bf231ea6 133\r
a3589760 134/**\r
bf231ea6 135 Function to submit SCSI inquiry command.\r
b91d5eca 136\r
137 Submit SCSI inquiry command with the SCSI request packet specified by this SCSI command and input\r
138 parameters, then return the status of Scsi unit execution.\r
139\r
52cd71dc 140 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 141\r
52cd71dc 142 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 143\r
52cd71dc 144 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 145\r
52cd71dc 146 If InquiryDataLength is NULL, then ASSERT().\r
a3589760 147\r
148 @param[in] ScsiIo SCSI IO Protocol to use\r
149 @param[in] Timeout The length of timeout period.\r
b91d5eca 150 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 151 @param[in, out] SenseDataLength The length of output sense data.\r
a3589760 152 @param[out] HostAdapterStatus The status of Host Adapter.\r
153 @param[out] TargetStatus The status of the target.\r
ee256e2c 154 @param[in, out] InquirydataBuffer A pointer to inquiry data buffer.\r
155 @param[in, out] InquiryDataLength The length of inquiry data buffer.\r
a3589760 156 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.\r
157\r
b91d5eca 158 @retval EFI_SUCCESS Command is executed successfully.\r
159 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
160 but the entire DataBuffer could not be transferred.\r
161 The actual number of bytes transferred is returned\r
162 in TransferLength.\r
163 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
164 there are too many SCSI Command Packets already \r
165 queued.\r
166 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
167 the SCSI Request Packet.\r
168 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
169 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
170 is not supported by the SCSI initiator(i.e., SCSI \r
171 Host Controller).\r
172 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
173 Request Packet to execute.\r
a3589760 174\r
bf231ea6 175**/\r
a02e796b 176EFI_STATUS\r
373b5cf9 177EFIAPI\r
d35be2a4 178ScsiInquiryCommand (\r
a02e796b 179 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
180 IN UINT64 Timeout,\r
181 IN VOID *SenseData,\r
182 IN OUT UINT8 *SenseDataLength,\r
183 OUT UINT8 *HostAdapterStatus,\r
184 OUT UINT8 *TargetStatus,\r
956a6dca 185 IN OUT VOID *InquiryDataBuffer,\r
a02e796b 186 IN OUT UINT32 *InquiryDataLength,\r
187 IN BOOLEAN EnableVitalProductData\r
188 )\r
a02e796b 189{\r
190 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
191 UINT64 Lun;\r
192 UINT8 *Target;\r
193 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
194 EFI_STATUS Status;\r
52cd71dc 195 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 196\r
8069d49e
LG
197 ASSERT (SenseDataLength != NULL);\r
198 ASSERT (HostAdapterStatus != NULL);\r
199 ASSERT (TargetStatus != NULL);\r
200 ASSERT (InquiryDataLength != NULL);\r
201 \r
202 if (ScsiIo == NULL) {\r
203 return EFI_INVALID_PARAMETER;\r
204 }\r
205\r
a02e796b 206 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 207 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 208\r
209 CommandPacket.Timeout = Timeout;\r
210 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
211 CommandPacket.InTransferLength= *InquiryDataLength;\r
212 CommandPacket.SenseData = SenseData;\r
213 CommandPacket.SenseDataLength = *SenseDataLength;\r
214 CommandPacket.Cdb = Cdb;\r
215\r
216 Target = &TargetArray[0];\r
217 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
218\r
219 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
52cd71dc 220 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 221 if (EnableVitalProductData) {\r
222 Cdb[1] |= 0x01;\r
223 }\r
224\r
225 if (*InquiryDataLength > 0xff) {\r
226 *InquiryDataLength = 0xff;\r
227 }\r
228\r
229 Cdb[4] = (UINT8) (*InquiryDataLength);\r
52cd71dc 230 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 231 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
232\r
233 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
234\r
235 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
236 *TargetStatus = CommandPacket.TargetStatus;\r
237 *SenseDataLength = CommandPacket.SenseDataLength;\r
238 *InquiryDataLength = CommandPacket.InTransferLength;\r
239\r
240 return Status;\r
241}\r
242\r
bf231ea6 243\r
a3589760 244/**\r
bf231ea6 245 Function to submit SCSI mode sense 10 command.\r
b91d5eca 246\r
247 Submit SCSI Mode Sense (10) command with the SCSI request packet specified by this SCSI command and\r
248 the input parameters, then return the status of Scsi unit execution.\r
249\r
52cd71dc 250 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 251\r
52cd71dc 252 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 253\r
52cd71dc 254 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 255\r
52cd71dc 256 If DataLength is NULL, then ASSERT().\r
a3589760 257\r
258 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
259 @param[in] Timeout The length of timeout period.\r
b91d5eca 260 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 261 @param[in, out] SenseDataLength The length of output sense data.\r
a3589760 262 @param[out] HostAdapterStatus The status of Host Adapter.\r
263 @param[out] TargetStatus The status of the target.\r
264 @param[in] DataBuffer A pointer to input data buffer.\r
ee256e2c 265 @param[in, out] DataLength The length of input data buffer.\r
a3589760 266 @param[in] DBDField The DBD Field (Optional).\r
267 @param[in] PageControl Page Control.\r
268 @param[in] PageCode Page code.\r
269\r
bf231ea6 270 @retval EFI_SUCCESS The status of the unit is tested successfully.\r
c7a54f25 271 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
bf231ea6
A
272 but the entire DataBuffer could not be transferred.\r
273 The actual number of bytes transferred is returned\r
274 in TransferLength.\r
275 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
276 there are too many SCSI Command Packets already \r
277 queued.\r
278 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
279 the SCSI Request Packet.\r
b91d5eca 280 @retval EFI_INVALID_PARAMETER ScsiIo is NULL. \r
bf231ea6
A
281 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
282 is not supported by the SCSI initiator(i.e., SCSI \r
283 Host Controller).\r
284 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
285 Request Packet to execute.\r
a3589760 286\r
bf231ea6 287**/\r
a02e796b 288EFI_STATUS\r
373b5cf9 289EFIAPI\r
d35be2a4 290ScsiModeSense10Command (\r
a02e796b 291 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
292 IN UINT64 Timeout,\r
293 IN VOID *SenseData,\r
294 IN OUT UINT8 *SenseDataLength,\r
295 OUT UINT8 *HostAdapterStatus,\r
296 OUT UINT8 *TargetStatus,\r
297 IN VOID *DataBuffer,\r
298 IN OUT UINT32 *DataLength,\r
299 IN UINT8 DBDField, OPTIONAL\r
300 IN UINT8 PageControl,\r
301 IN UINT8 PageCode\r
302 )\r
a02e796b 303{\r
304 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
305 UINT64 Lun;\r
306 UINT8 *Target;\r
307 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
308 EFI_STATUS Status;\r
52cd71dc 309 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 310\r
8069d49e
LG
311 ASSERT (SenseDataLength != NULL);\r
312 ASSERT (HostAdapterStatus != NULL);\r
313 ASSERT (TargetStatus != NULL);\r
314 ASSERT (DataLength != NULL);\r
315 \r
316 if (ScsiIo == NULL) {\r
317 return EFI_INVALID_PARAMETER;\r
318 }\r
319\r
a02e796b 320 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 321 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 322\r
323 CommandPacket.Timeout = Timeout;\r
324 CommandPacket.InDataBuffer = DataBuffer;\r
325 CommandPacket.SenseData = SenseData;\r
326 CommandPacket.InTransferLength= *DataLength;\r
327 CommandPacket.Cdb = Cdb;\r
328 //\r
329 // Fill Cdb for Mode Sense (10) Command\r
330 //\r
331 Target = &TargetArray[0];\r
332 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
333\r
334 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
52cd71dc
LG
335 //\r
336 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
337 //\r
338 Cdb[1] = (UINT8) ((Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));\r
339 //\r
340 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
341 //\r
a02e796b 342 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));\r
343 Cdb[7] = (UINT8) (*DataLength >> 8);\r
344 Cdb[8] = (UINT8) (*DataLength);\r
345\r
52cd71dc 346 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 347 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
348 CommandPacket.SenseDataLength = *SenseDataLength;\r
349\r
350 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
351\r
352 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
353 *TargetStatus = CommandPacket.TargetStatus;\r
354 *SenseDataLength = CommandPacket.SenseDataLength;\r
355 *DataLength = CommandPacket.InTransferLength;\r
356\r
357 return Status;\r
358}\r
359\r
bf231ea6 360\r
a3589760 361/**\r
bf231ea6 362 Function to submit SCSI request sense command.\r
b91d5eca 363\r
364 Submit SCSI request sense command with the SCSI requested packet specified by this\r
365 SCSI command, TimeOut and SenseData, and then return the status of scsi unit execution.\r
366\r
52cd71dc 367 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 368 \r
52cd71dc 369 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 370 \r
52cd71dc 371 If TargetStatus is NULL, then ASSERT().\r
a3589760 372\r
b91d5eca 373 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
374 @param[in] Timeout The length of timeout period.\r
375 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 376 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 377 @param[out] HostAdapterStatus The status of Host Adapter.\r
378 @param[out] TargetStatus The status of the target.\r
379\r
380 @retval EFI_SUCCESS Command is executed successfully.\r
381 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
382 too many SCSI Command Packets already queued.\r
383 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
384 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
385 the SCSI initiator(i.e., SCSI Host Controller)\r
386 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
387 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
a3589760 388\r
bf231ea6 389**/\r
a02e796b 390EFI_STATUS\r
373b5cf9 391EFIAPI\r
d35be2a4 392ScsiRequestSenseCommand (\r
a02e796b 393 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
394 IN UINT64 Timeout,\r
395 IN VOID *SenseData,\r
396 IN OUT UINT8 *SenseDataLength,\r
397 OUT UINT8 *HostAdapterStatus,\r
398 OUT UINT8 *TargetStatus\r
399 )\r
a02e796b 400{\r
401 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
402 UINT64 Lun;\r
403 UINT8 *Target;\r
404 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
405 EFI_STATUS Status;\r
52cd71dc 406 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 407\r
8069d49e
LG
408 ASSERT (SenseDataLength != NULL);\r
409 ASSERT (HostAdapterStatus != NULL);\r
410 ASSERT (TargetStatus != NULL);\r
411 \r
412 if (ScsiIo == NULL) {\r
413 return EFI_INVALID_PARAMETER;\r
414 }\r
415\r
a02e796b 416 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 417 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 418\r
419 CommandPacket.Timeout = Timeout;\r
420 CommandPacket.InDataBuffer = SenseData;\r
421 CommandPacket.SenseData = NULL;\r
422 CommandPacket.InTransferLength= *SenseDataLength;\r
423 CommandPacket.Cdb = Cdb;\r
424 //\r
425 // Fill Cdb for Request Sense Command\r
426 //\r
427 Target = &TargetArray[0];\r
428 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
429\r
430 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
52cd71dc 431 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 432 Cdb[4] = (UINT8) (*SenseDataLength);\r
433\r
52cd71dc 434 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 435 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
436 CommandPacket.SenseDataLength = 0;\r
437\r
438 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
439\r
440 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
441 *TargetStatus = CommandPacket.TargetStatus;\r
442 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
443\r
444 return Status;\r
445}\r
446\r
bf231ea6 447\r
a3589760 448/**\r
bf231ea6 449 Function to submit read capacity command.\r
b91d5eca 450\r
451 Submit SCSI read capacity command with the SCSI request packet specified by this SCSI \r
452 command and the input parameters, and then return the status of Scsi unit execution.\r
453\r
52cd71dc 454 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 455\r
52cd71dc 456 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 457\r
52cd71dc 458 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 459\r
52cd71dc 460 If DataLength is NULL, then ASSERT().\r
bf231ea6 461\r
b91d5eca 462 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
463 @param[in] Timeout The length of timeout period.\r
464 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 465 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 466 @param[out] HostAdapterStatus The status of Host Adapter.\r
467 @param[out] TargetStatus The status of the target.\r
468 @param[out] DataBuffer A pointer to a data buffer.\r
ee256e2c 469 @param[in, out] DataLength The length of data buffer.\r
b91d5eca 470 @param[in] PMI Partial medium indicator.\r
471\r
472 @retval EFI_SUCCESS Command is executed successfully.\r
473 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
474 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
475 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
476 SCSI Command Packets already queued.\r
477 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
478 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
479 the SCSI initiator(i.e., SCSI Host Controller)\r
480 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
481 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
a3589760 482\r
bf231ea6 483**/\r
a02e796b 484EFI_STATUS\r
373b5cf9 485EFIAPI\r
d35be2a4 486ScsiReadCapacityCommand (\r
a02e796b 487 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
488 IN UINT64 Timeout,\r
489 IN VOID *SenseData,\r
490 IN OUT UINT8 *SenseDataLength,\r
491 OUT UINT8 *HostAdapterStatus,\r
492 OUT UINT8 *TargetStatus,\r
493 OUT VOID *DataBuffer,\r
494 IN OUT UINT32 *DataLength,\r
495 IN BOOLEAN PMI\r
496 )\r
a02e796b 497{\r
498 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
499 UINT64 Lun;\r
500 UINT8 *Target;\r
501 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
502 EFI_STATUS Status;\r
52cd71dc 503 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 504\r
8069d49e
LG
505 ASSERT (SenseDataLength != NULL);\r
506 ASSERT (HostAdapterStatus != NULL);\r
507 ASSERT (TargetStatus != NULL);\r
508 ASSERT (DataLength != NULL);\r
509 \r
510 if (ScsiIo == NULL) {\r
511 return EFI_INVALID_PARAMETER;\r
512 }\r
513\r
a02e796b 514 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 515 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 516\r
517 CommandPacket.Timeout = Timeout;\r
518 CommandPacket.InDataBuffer = DataBuffer;\r
519 CommandPacket.SenseData = SenseData;\r
520 CommandPacket.InTransferLength= *DataLength;\r
521 CommandPacket.Cdb = Cdb;\r
522 //\r
523 // Fill Cdb for Read Capacity Command\r
524 //\r
525 Target = &TargetArray[0];\r
526 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
527\r
528 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
52cd71dc 529 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 530 if (!PMI) {\r
531 //\r
532 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
533 //\r
534 ZeroMem ((Cdb + 2), 4);\r
535 } else {\r
536 Cdb[8] |= 0x01;\r
537 }\r
538\r
52cd71dc 539 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 540 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
541 CommandPacket.SenseDataLength = *SenseDataLength;\r
542\r
543 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
544\r
545 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
546 *TargetStatus = CommandPacket.TargetStatus;\r
547 *SenseDataLength = CommandPacket.SenseDataLength;\r
548 *DataLength = CommandPacket.InTransferLength;\r
549\r
550 return Status;\r
551}\r
552\r
bf231ea6 553\r
a3589760 554/**\r
bf231ea6 555 Function to submit read 10 command.\r
b91d5eca 556\r
557 Submit SCSI read (10) command with the SCSI request packet specified by this SCSI command \r
558 and the input parameters, and then return the status of Scsi unit execution.\r
559\r
52cd71dc 560 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 561\r
52cd71dc 562 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 563\r
52cd71dc 564 If TargetStatus is NULL, then ASSERT().\r
a3589760 565\r
b91d5eca 566 If DataLength is NULL, then ASSERT().\r
a3589760 567\r
b91d5eca 568 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
569 @param[in] Timeout The length of timeout period.\r
570 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 571 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 572 @param[out] HostAdapterStatus The status of Host Adapter.\r
573 @param[out] TargetStatus The status of the target.\r
574 @param[out] DataBuffer Read 10 command data.\r
ee256e2c 575 @param[in, out] DataLength The length of data buffer.\r
b91d5eca 576 @param[in] StartLba The start address of LBA.\r
577 @param[in] SectorSize The sector size.\r
578\r
579 @retval EFI_SUCCESS Command is executed successfully.\r
580 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
581 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
582 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
583 SCSI Command Packets already queued.\r
584 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
585 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
586 the SCSI initiator(i.e., SCSI Host Controller)\r
587 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
588 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
a3589760 589\r
bf231ea6 590**/\r
a02e796b 591EFI_STATUS\r
373b5cf9 592EFIAPI\r
d35be2a4 593ScsiRead10Command (\r
a02e796b 594 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
595 IN UINT64 Timeout,\r
596 IN VOID *SenseData,\r
597 IN OUT UINT8 *SenseDataLength,\r
598 OUT UINT8 *HostAdapterStatus,\r
599 OUT UINT8 *TargetStatus,\r
600 OUT VOID *DataBuffer,\r
601 IN OUT UINT32 *DataLength,\r
602 IN UINT32 StartLba,\r
603 IN UINT32 SectorSize\r
604 )\r
a02e796b 605{\r
606 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
607 UINT64 Lun;\r
608 UINT8 *Target;\r
609 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
610 EFI_STATUS Status;\r
52cd71dc 611 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 612\r
8069d49e
LG
613 ASSERT (SenseDataLength != NULL);\r
614 ASSERT (HostAdapterStatus != NULL);\r
615 ASSERT (TargetStatus != NULL);\r
616 ASSERT (DataLength != NULL);\r
617 \r
618 if (ScsiIo == NULL) {\r
619 return EFI_INVALID_PARAMETER;\r
620 }\r
621\r
a02e796b 622 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 623 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 624\r
625 CommandPacket.Timeout = Timeout;\r
626 CommandPacket.InDataBuffer = DataBuffer;\r
627 CommandPacket.SenseData = SenseData;\r
628 CommandPacket.InTransferLength= *DataLength;\r
629 CommandPacket.Cdb = Cdb;\r
630 //\r
631 // Fill Cdb for Read (10) Command\r
632 //\r
633 Target = &TargetArray[0];\r
634 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
635\r
636 Cdb[0] = EFI_SCSI_OP_READ10;\r
52cd71dc 637 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 638 Cdb[2] = (UINT8) (StartLba >> 24);\r
639 Cdb[3] = (UINT8) (StartLba >> 16);\r
640 Cdb[4] = (UINT8) (StartLba >> 8);\r
641 Cdb[5] = (UINT8) (StartLba & 0xff);\r
642 Cdb[7] = (UINT8) (SectorSize >> 8);\r
643 Cdb[8] = (UINT8) (SectorSize & 0xff);\r
644\r
52cd71dc 645 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 646 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
647 CommandPacket.SenseDataLength = *SenseDataLength;\r
648\r
649 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
650\r
651 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
652 *TargetStatus = CommandPacket.TargetStatus;\r
653 *SenseDataLength = CommandPacket.SenseDataLength;\r
654 *DataLength = CommandPacket.InTransferLength;\r
655\r
656 return Status;\r
657}\r
658\r
bf231ea6 659\r
a3589760 660/**\r
bf231ea6 661 Function to submit SCSI write 10 command.\r
b91d5eca 662\r
663 Submit SCSI write (10) command with the SCSI request packet specified by this SCSI command and the\r
664 input parameters, and then return the status of Scsi unit execution.\r
665\r
52cd71dc 666 If SenseDataLength is NULL, then ASSERT().\r
b91d5eca 667\r
52cd71dc 668 If HostAdapterStatus is NULL, then ASSERT().\r
b91d5eca 669\r
52cd71dc 670 If TargetStatus is NULL, then ASSERT().\r
a3589760 671\r
b91d5eca 672 If DataLength is NULL, then ASSERT().\r
a3589760 673\r
b91d5eca 674 @param[in] ScsiIo SCSI IO Protocol to use\r
675 @param[in] Timeout The length of timeout period.\r
676 @param[in] SenseData A pointer to output sense data.\r
ee256e2c 677 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 678 @param[out] HostAdapterStatus The status of Host Adapter.\r
679 @param[out] TargetStatus The status of the target.\r
680 @param[out] DataBuffer A pointer to a data buffer.\r
ee256e2c 681 @param[in, out] DataLength The length of data buffer.\r
b91d5eca 682 @param[in] StartLba The start address of LBA.\r
683 @param[in] SectorSize The sector size.\r
684\r
685 @retval EFI_SUCCESS Command is executed successfully.\r
686 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
687 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
688 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
689 SCSI Command Packets already queued.\r
690 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
691 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
692 the SCSI initiator(i.e., SCSI Host Controller)\r
693 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
694 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
a3589760 695\r
bf231ea6 696**/\r
a02e796b 697EFI_STATUS\r
373b5cf9 698EFIAPI\r
d35be2a4 699ScsiWrite10Command (\r
a02e796b 700 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
701 IN UINT64 Timeout,\r
702 IN VOID *SenseData,\r
703 IN OUT UINT8 *SenseDataLength,\r
704 OUT UINT8 *HostAdapterStatus,\r
705 OUT UINT8 *TargetStatus,\r
706 OUT VOID *DataBuffer,\r
707 IN OUT UINT32 *DataLength,\r
708 IN UINT32 StartLba,\r
709 IN UINT32 SectorSize\r
710 )\r
a02e796b 711{\r
712 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
713 UINT64 Lun;\r
714 UINT8 *Target;\r
715 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
716 EFI_STATUS Status;\r
52cd71dc 717 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 718\r
8069d49e
LG
719 ASSERT (SenseDataLength != NULL);\r
720 ASSERT (HostAdapterStatus != NULL);\r
721 ASSERT (TargetStatus != NULL);\r
722 ASSERT (DataLength != NULL);\r
723 \r
724 if (ScsiIo == NULL) {\r
725 return EFI_INVALID_PARAMETER;\r
726 }\r
727\r
a02e796b 728 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 729 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 730\r
731 CommandPacket.Timeout = Timeout;\r
732 CommandPacket.OutDataBuffer = DataBuffer;\r
733 CommandPacket.SenseData = SenseData;\r
734 CommandPacket.OutTransferLength= *DataLength;\r
735 CommandPacket.Cdb = Cdb;\r
736 //\r
737 // Fill Cdb for Write (10) Command\r
738 //\r
739 Target = &TargetArray[0];\r
740 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
741\r
742 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
52cd71dc 743 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 744 Cdb[2] = (UINT8) (StartLba >> 24);\r
745 Cdb[3] = (UINT8) (StartLba >> 16);\r
746 Cdb[4] = (UINT8) (StartLba >> 8);\r
747 Cdb[5] = (UINT8) StartLba;\r
748 Cdb[7] = (UINT8) (SectorSize >> 8);\r
749 Cdb[8] = (UINT8) SectorSize;\r
750\r
52cd71dc 751 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 752 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
753 CommandPacket.SenseDataLength = *SenseDataLength;\r
754\r
755 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
756\r
757 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
758 *TargetStatus = CommandPacket.TargetStatus;\r
759 *SenseDataLength = CommandPacket.SenseDataLength;\r
ba7e162e 760 *DataLength = CommandPacket.OutTransferLength;\r
a02e796b 761\r
762 return Status;\r
763}\r
373b5cf9 764\r