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