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