]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
synchronize the MdePkg/Include/Library/BaseLib.h and the MDE_Library_Spec.
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
... / ...
CommitLineData
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
4 Copyright (c) 2006 - 2008, 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
14\r
15\r
16#include <Uefi.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiScsiLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20\r
21#include <IndustryStandard/Scsi.h>\r
22\r
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
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
39\r
40/**\r
41 Function test the ready status of the SCSI unit.\r
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
46 If SenseDataLength is NULL, then ASSERT().\r
47\r
48 If HostAdapterStatus is NULL, then ASSERT().\r
49\r
50 If TargetStatus is NULL, then ASSERT().\r
51\r
52 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
53 @param[in] Timeout The length of timeout period.\r
54 @param[in] SenseData A pointer to output sense data.\r
55 @param[out] SenseDataLength The length of output sense data.\r
56 @param[out] HostAdapterStatus The status of Host Adapter.\r
57 @param[out] TargetStatus The status of the target.\r
58\r
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
69 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
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
75\r
76**/\r
77EFI_STATUS\r
78EFIAPI\r
79ScsiTestUnitReadyCommand (\r
80 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
81 IN UINT64 Timeout,\r
82 IN VOID *SenseData,\r
83 OUT UINT8 *SenseDataLength,\r
84 OUT UINT8 *HostAdapterStatus,\r
85 OUT UINT8 *TargetStatus\r
86 )\r
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
93 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
94\r
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
102\r
103 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
104 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
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
120 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
121 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
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
133\r
134/**\r
135 Function to submit SCSI inquiry command.\r
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
140 If SenseDataLength is NULL, then ASSERT().\r
141\r
142 If HostAdapterStatus is NULL, then ASSERT().\r
143\r
144 If TargetStatus is NULL, then ASSERT().\r
145\r
146 If InquiryDataLength is NULL, then ASSERT().\r
147\r
148 @param[in] ScsiIo SCSI IO Protocol to use\r
149 @param[in] Timeout The length of timeout period.\r
150 @param[in] SenseData A pointer to output sense data.\r
151 @param[in, out] SenseDataLength The length of output sense data.\r
152 @param[out] HostAdapterStatus The status of Host Adapter.\r
153 @param[out] TargetStatus The status of the target.\r
154 @param[in, out] InquiryDataBuffer A pointer to inquiry data buffer.\r
155 @param[in, out] InquiryDataLength The length of inquiry data buffer.\r
156 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.\r
157\r
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
174\r
175**/\r
176EFI_STATUS\r
177EFIAPI\r
178ScsiInquiryCommand (\r
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
185 IN OUT VOID *InquiryDataBuffer,\r
186 IN OUT UINT32 *InquiryDataLength,\r
187 IN BOOLEAN EnableVitalProductData\r
188 )\r
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
195 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
196\r
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
206 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
207 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
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
220 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
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
230 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
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
243\r
244/**\r
245 Function to submit SCSI mode sense 10 command.\r
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
250 If SenseDataLength is NULL, then ASSERT().\r
251\r
252 If HostAdapterStatus is NULL, then ASSERT().\r
253\r
254 If TargetStatus is NULL, then ASSERT().\r
255\r
256 If DataLength is NULL, then ASSERT().\r
257\r
258 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
259 @param[in] Timeout The length of timeout period.\r
260 @param[in] SenseData A pointer to output sense data.\r
261 @param[in, out] SenseDataLength The length of output sense data.\r
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
265 @param[in, out] DataLength The length of input data buffer.\r
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
270 @retval EFI_SUCCESS The status of the unit is tested successfully.\r
271 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
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
280 @retval EFI_INVALID_PARAMETER ScsiIo is NULL. \r
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
286\r
287**/\r
288EFI_STATUS\r
289EFIAPI\r
290ScsiModeSense10Command (\r
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
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
309 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
310\r
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
320 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
321 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
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
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
342 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));\r
343 Cdb[7] = (UINT8) (*DataLength >> 8);\r
344 Cdb[8] = (UINT8) (*DataLength);\r
345\r
346 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
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
360\r
361/**\r
362 Function to submit SCSI request sense command.\r
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
367 If SenseDataLength is NULL, then ASSERT().\r
368 \r
369 If HostAdapterStatus is NULL, then ASSERT().\r
370 \r
371 If TargetStatus is NULL, then ASSERT().\r
372\r
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
376 @param[in, out] SenseDataLength The length of output sense data.\r
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
388\r
389**/\r
390EFI_STATUS\r
391EFIAPI\r
392ScsiRequestSenseCommand (\r
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
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
406 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
407\r
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
416 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
417 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
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
431 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
432 Cdb[4] = (UINT8) (*SenseDataLength);\r
433\r
434 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
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
447\r
448/**\r
449 Function to submit read capacity command.\r
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
454 If SenseDataLength is NULL, then ASSERT().\r
455\r
456 If HostAdapterStatus is NULL, then ASSERT().\r
457\r
458 If TargetStatus is NULL, then ASSERT().\r
459\r
460 If DataLength is NULL, then ASSERT().\r
461\r
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
465 @param[in, out] SenseDataLength The length of output sense data.\r
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
469 @param[in, out] DataLength The length of data buffer.\r
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
482\r
483**/\r
484EFI_STATUS\r
485EFIAPI\r
486ScsiReadCapacityCommand (\r
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
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
503 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
504\r
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
514 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
515 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
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
529 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
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
539 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
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
553\r
554/**\r
555 Function to submit read 10 command.\r
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
560 If SenseDataLength is NULL, then ASSERT().\r
561\r
562 If HostAdapterStatus is NULL, then ASSERT().\r
563\r
564 If TargetStatus is NULL, then ASSERT().\r
565\r
566 If DataLength is NULL, then ASSERT().\r
567\r
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
571 @param[in, out] SenseDataLength The length of output sense data.\r
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
575 @param[in, out] DataLength The length of data buffer.\r
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
589\r
590**/\r
591EFI_STATUS\r
592EFIAPI\r
593ScsiRead10Command (\r
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
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
611 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
612\r
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
622 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
623 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
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
637 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
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
645 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
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
659\r
660/**\r
661 Function to submit SCSI write 10 command.\r
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
666 If SenseDataLength is NULL, then ASSERT().\r
667\r
668 If HostAdapterStatus is NULL, then ASSERT().\r
669\r
670 If TargetStatus is NULL, then ASSERT().\r
671\r
672 If DataLength is NULL, then ASSERT().\r
673\r
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
677 @param[in, out] SenseDataLength The length of output sense data.\r
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
681 @param[in, out] DataLength The length of data buffer.\r
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
695\r
696**/\r
697EFI_STATUS\r
698EFIAPI\r
699ScsiWrite10Command (\r
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
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
717 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
718\r
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
728 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
729 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
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
743 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
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
751 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
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
760 *DataLength = CommandPacket.OutTransferLength;\r
761\r
762 return Status;\r
763}\r
764\r