]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
MdePkg/UefiScsiLib: comments update to add EFI_INVALID_PARAMETER status
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
1 /** @file
2 UEFI SCSI Library implementation
3
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include <Uefi.h>
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiScsiLib.h>
20 #include <Library/BaseMemoryLib.h>
21
22 #include <IndustryStandard/Scsi.h>
23
24
25 //
26 // Scsi Command Length
27 //
28 #define EFI_SCSI_OP_LENGTH_SIX 0x6
29 #define EFI_SCSI_OP_LENGTH_TEN 0xa
30 #define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
31
32
33
34 /**
35 Execute Test Unit Ready SCSI command on a specific SCSI target.
36
37 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.
38 If Timeout is zero, then this function waits indefinitely for the command to complete.
39 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
40 If ScsiIo is NULL, then ASSERT().
41 If SenseDataLength is NULL, then ASSERT().
42 If HostAdapterStatus is NULL, then ASSERT().
43 If TargetStatus is NULL, then ASSERT().
44
45 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
46 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
47 gets returned.
48
49 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
50 for the specific SCSI target.
51 @param[in] Timeout The timeout in 100 ns units to use for the execution
52 of this SCSI Request Packet. A Timeout value of
53 zero means that this function will wait indefinitely
54 for the SCSI Request Packet to execute. If Timeout
55 is greater than zero, then this function will return
56 EFI_TIMEOUT if the time required to execute the SCSI
57 Request Packet is greater than Timeout.
58 @param[in, out] SenseData A pointer to sense data that was generated by
59 the execution of the SCSI Request Packet. This
60 buffer must be allocated by the caller.
61 If SenseDataLength is 0, then this parameter is
62 optional and may be NULL.
63 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of
64 the SenseData buffer. On output, a pointer to
65 the number of bytes written to the SenseData buffer.
66 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces
67 the SCSI bus containing the SCSI target specified by
68 ScsiIo when the SCSI Request Packet was executed.
69 See the EFI SCSI I/O Protocol in the UEFI Specification
70 for details on the possible return values.
71 @param[out] TargetStatus The status returned by the SCSI target specified
72 by ScsiIo when the SCSI Request Packet was executed
73 on the SCSI Host Controller. See the EFI SCSI I/O
74 Protocol in the UEFI Specification for details on
75 the possible return values.
76
77 @retval EFI_SUCCESS The command was executed successfully.
78 See HostAdapterStatus, TargetStatus, SenseDataLength,
79 and SenseData in that order for additional status
80 information.
81 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
82 there are too many SCSI Command Packets already
83 queued. The SCSI Request Packet was not sent, so
84 no additional status information is available.
85 The caller may retry again later.
86 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
87 SCSI Request Packet. See HostAdapterStatus,
88 TargetStatus, SenseDataLength, and SenseData in that
89 order for additional status information.
90 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
91 is not supported by the SCSI initiator(i.e., SCSI
92 Host Controller). The SCSI Request Packet was not
93 sent, so no additional status information is available.
94 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
95 Packet to execute. See HostAdapterStatus, TargetStatus,
96 SenseDataLength, and SenseData in that order for
97 additional status information.
98 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
99
100 **/
101 EFI_STATUS
102 EFIAPI
103 ScsiTestUnitReadyCommand (
104 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
105 IN UINT64 Timeout,
106 IN OUT VOID *SenseData, OPTIONAL
107 IN OUT UINT8 *SenseDataLength,
108 OUT UINT8 *HostAdapterStatus,
109 OUT UINT8 *TargetStatus
110 )
111 {
112 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
113 EFI_STATUS Status;
114 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
115
116 ASSERT (SenseDataLength != NULL);
117 ASSERT (HostAdapterStatus != NULL);
118 ASSERT (TargetStatus != NULL);
119 ASSERT (ScsiIo != NULL);
120
121 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
122 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
123
124 CommandPacket.Timeout = Timeout;
125 CommandPacket.InDataBuffer = NULL;
126 CommandPacket.InTransferLength= 0;
127 CommandPacket.OutDataBuffer = NULL;
128 CommandPacket.OutTransferLength= 0;
129 CommandPacket.SenseData = SenseData;
130 CommandPacket.Cdb = Cdb;
131 //
132 // Fill Cdb for Test Unit Ready Command
133 //
134 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
135 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
136 CommandPacket.SenseDataLength = *SenseDataLength;
137
138 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
139
140 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
141 *TargetStatus = CommandPacket.TargetStatus;
142 *SenseDataLength = CommandPacket.SenseDataLength;
143
144 return Status;
145 }
146
147
148 /**
149 Execute Inquiry SCSI command on a specific SCSI target.
150
151 Executes the Inquiry command on the SCSI target specified by ScsiIo.
152 If Timeout is zero, then this function waits indefinitely for the command to complete.
153 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
154 If ScsiIo is NULL, then ASSERT().
155 If SenseDataLength is NULL, then ASSERT().
156 If HostAdapterStatus is NULL, then ASSERT().
157 If TargetStatus is NULL, then ASSERT().
158 If InquiryDataLength is NULL, then ASSERT().
159
160 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
161 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
162 gets returned.
163
164 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
165 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
166 EFI_INVALID_PARAMETER gets returned.
167
168 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
169 for the specific SCSI target.
170 @param[in] Timeout The timeout in 100 ns units to use for the
171 execution of this SCSI Request Packet. A Timeout
172 value of zero means that this function will wait
173 indefinitely for the SCSI Request Packet to execute.
174 If Timeout is greater than zero, then this function
175 will return EFI_TIMEOUT if the time required to
176 execute the SCSI Request Packet is greater than Timeout.
177 @param[in, out] SenseData A pointer to sense data that was generated
178 by the execution of the SCSI Request Packet.
179 This buffer must be allocated by the caller.
180 If SenseDataLength is 0, then this parameter
181 is optional and may be NULL.
182 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
183 On output, the number of bytes written to the SenseData buffer.
184 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
185 produces the SCSI bus containing the SCSI
186 target specified by ScsiIo when the SCSI
187 Request Packet was executed. See the EFI
188 SCSI I/O Protocol in the UEFI Specification
189 for details on the possible return values.
190 @param[out] TargetStatus The status returned by the SCSI target specified
191 by ScsiIo when the SCSI Request Packet was
192 executed on the SCSI Host Controller.
193 See the EFI SCSI I/O Protocol in the UEFI
194 Specification for details on the possible
195 return values.
196 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
197 by the execution of the SCSI Request Packet.
198 This buffer must be allocated by the caller.
199 If InquiryDataLength is 0, then this parameter
200 is optional and may be NULL.
201 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
202 of the InquiryDataBuffer buffer.
203 On output, a pointer to the number of bytes
204 written to the InquiryDataBuffer buffer.
205 @param[in] EnableVitalProductData If TRUE, then the supported vital product
206 data for the PageCode is returned in InquiryDataBuffer.
207 If FALSE, then the standard inquiry data is
208 returned in InquiryDataBuffer and PageCode is ignored.
209 @param[in] PageCode The page code of the vital product data.
210 It's ignored if EnableVitalProductData is FALSE.
211
212 @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,
213 TargetStatus, SenseDataLength, and SenseData in that order
214 for additional status information.
215 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
216 InquiryDataBuffer could not be transferred. The actual
217 number of bytes transferred is returned in InquiryDataLength.
218 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
219 are too many SCSI Command Packets already queued.
220 The SCSI Request Packet was not sent, so no additional
221 status information is available. The caller may retry again later.
222 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
223 Request Packet. See HostAdapterStatus, TargetStatus,
224 SenseDataLength, and SenseData in that order for additional
225 status information.
226 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
227 supported by the SCSI initiator(i.e., SCSI Host Controller).
228 The SCSI Request Packet was not sent, so no additional
229 status information is available.
230 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
231 Packet to execute. See HostAdapterStatus, TargetStatus,
232 SenseDataLength, and SenseData in that order for
233 additional status information.
234 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 ScsiInquiryCommandEx (
240 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
241 IN UINT64 Timeout,
242 IN OUT VOID *SenseData, OPTIONAL
243 IN OUT UINT8 *SenseDataLength,
244 OUT UINT8 *HostAdapterStatus,
245 OUT UINT8 *TargetStatus,
246 IN OUT VOID *InquiryDataBuffer, OPTIONAL
247 IN OUT UINT32 *InquiryDataLength,
248 IN BOOLEAN EnableVitalProductData,
249 IN UINT8 PageCode
250 )
251 {
252 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
253 EFI_STATUS Status;
254 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
255
256 ASSERT (SenseDataLength != NULL);
257 ASSERT (HostAdapterStatus != NULL);
258 ASSERT (TargetStatus != NULL);
259 ASSERT (InquiryDataLength != NULL);
260 ASSERT (ScsiIo != NULL);
261
262 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
263 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
264
265 CommandPacket.Timeout = Timeout;
266 CommandPacket.InDataBuffer = InquiryDataBuffer;
267 CommandPacket.InTransferLength= *InquiryDataLength;
268 CommandPacket.SenseData = SenseData;
269 CommandPacket.SenseDataLength = *SenseDataLength;
270 CommandPacket.Cdb = Cdb;
271
272 Cdb[0] = EFI_SCSI_OP_INQUIRY;
273 if (EnableVitalProductData) {
274 Cdb[1] |= 0x01;
275 Cdb[2] = PageCode;
276 }
277
278 if (*InquiryDataLength > 0xff) {
279 *InquiryDataLength = 0xff;
280 }
281
282 Cdb[4] = (UINT8) (*InquiryDataLength);
283 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
284 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
285
286 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
287
288 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
289 *TargetStatus = CommandPacket.TargetStatus;
290 *SenseDataLength = CommandPacket.SenseDataLength;
291 *InquiryDataLength = CommandPacket.InTransferLength;
292
293 return Status;
294 }
295
296
297 /**
298 Execute Inquiry SCSI command on a specific SCSI target.
299
300 Executes the Inquiry command on the SCSI target specified by ScsiIo.
301 If Timeout is zero, then this function waits indefinitely for the command to complete.
302 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
303 If ScsiIo is NULL, then ASSERT().
304 If SenseDataLength is NULL, then ASSERT().
305 If HostAdapterStatus is NULL, then ASSERT().
306 If TargetStatus is NULL, then ASSERT().
307 If InquiryDataLength is NULL, then ASSERT().
308
309 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
310 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
311 gets returned.
312
313 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
314 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
315 EFI_INVALID_PARAMETER gets returned.
316
317 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
318 for the specific SCSI target.
319 @param[in] Timeout The timeout in 100 ns units to use for the
320 execution of this SCSI Request Packet. A Timeout
321 value of zero means that this function will wait
322 indefinitely for the SCSI Request Packet to execute.
323 If Timeout is greater than zero, then this function
324 will return EFI_TIMEOUT if the time required to
325 execute the SCSI Request Packet is greater than Timeout.
326 @param[in, out] SenseData A pointer to sense data that was generated
327 by the execution of the SCSI Request Packet.
328 This buffer must be allocated by the caller.
329 If SenseDataLength is 0, then this parameter
330 is optional and may be NULL.
331 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
332 On output, the number of bytes written to the SenseData buffer.
333 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
334 produces the SCSI bus containing the SCSI
335 target specified by ScsiIo when the SCSI
336 Request Packet was executed. See the EFI
337 SCSI I/O Protocol in the UEFI Specification
338 for details on the possible return values.
339 @param[out] TargetStatus The status returned by the SCSI target specified
340 by ScsiIo when the SCSI Request Packet was
341 executed on the SCSI Host Controller.
342 See the EFI SCSI I/O Protocol in the UEFI
343 Specification for details on the possible
344 return values.
345 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
346 by the execution of the SCSI Request Packet.
347 This buffer must be allocated by the caller.
348 If InquiryDataLength is 0, then this parameter
349 is optional and may be NULL.
350 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
351 of the InquiryDataBuffer buffer.
352 On output, a pointer to the number of bytes
353 written to the InquiryDataBuffer buffer.
354 @param[in] EnableVitalProductData If TRUE, then the supported vital product
355 data is returned in InquiryDataBuffer.
356 If FALSE, then the standard inquiry data is
357 returned in InquiryDataBuffer.
358
359 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
360 TargetStatus, SenseDataLength, and SenseData in that order
361 for additional status information.
362 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
363 InquiryDataBuffer could not be transferred. The actual
364 number of bytes transferred is returned in InquiryDataLength.
365 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
366 are too many SCSI Command Packets already queued.
367 The SCSI Request Packet was not sent, so no additional
368 status information is available. The caller may retry again later.
369 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
370 Request Packet. See HostAdapterStatus, TargetStatus,
371 SenseDataLength, and SenseData in that order for additional
372 status information.
373 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
374 supported by the SCSI initiator(i.e., SCSI Host Controller).
375 The SCSI Request Packet was not sent, so no additional
376 status information is available.
377 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
378 Packet to execute. See HostAdapterStatus, TargetStatus,
379 SenseDataLength, and SenseData in that order for
380 additional status information.
381 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
382
383 **/
384 EFI_STATUS
385 EFIAPI
386 ScsiInquiryCommand (
387 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
388 IN UINT64 Timeout,
389 IN OUT VOID *SenseData, OPTIONAL
390 IN OUT UINT8 *SenseDataLength,
391 OUT UINT8 *HostAdapterStatus,
392 OUT UINT8 *TargetStatus,
393 IN OUT VOID *InquiryDataBuffer, OPTIONAL
394 IN OUT UINT32 *InquiryDataLength,
395 IN BOOLEAN EnableVitalProductData
396 )
397 {
398 return ScsiInquiryCommandEx (
399 ScsiIo,
400 Timeout,
401 SenseData,
402 SenseDataLength,
403 HostAdapterStatus,
404 TargetStatus,
405 InquiryDataBuffer,
406 InquiryDataLength,
407 EnableVitalProductData,
408 0
409 );
410 }
411
412 /**
413 Execute Mode Sense(10) SCSI command on a specific SCSI target.
414
415 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
416 If Timeout is zero, then this function waits indefinitely for the command to complete.
417 If Timeout is greater than zero, then the command is executed and will timeout
418 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
419 are used to construct the CDB for this SCSI command.
420 If ScsiIo is NULL, then ASSERT().
421 If SenseDataLength is NULL, then ASSERT().
422 If HostAdapterStatus is NULL, then ASSERT().
423 If TargetStatus is NULL, then ASSERT().
424 If DataLength is NULL, then ASSERT().
425
426 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
427 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
428 gets returned.
429
430 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
431 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
432 gets returned.
433
434 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
435 for the specific SCSI target.
436 @param[in] Timeout The timeout in 100 ns units to use for the
437 execution of this SCSI Request Packet. A Timeout
438 value of zero means that this function will wait
439 indefinitely for the SCSI Request Packet to execute.
440 If Timeout is greater than zero, then this function
441 will return EFI_TIMEOUT if the time required to
442 execute the SCSI Request Packet is greater than Timeout.
443 @param[in, out] SenseData A pointer to sense data that was generated
444 by the execution of the SCSI Request Packet.
445 This buffer must be allocated by the caller.
446 If SenseDataLength is 0, then this parameter
447 is optional and may be NULL.
448 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
449 On output, the number of bytes written to the SenseData buffer.
450 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
451 produces the SCSI bus containing the SCSI target
452 specified by ScsiIo when the SCSI Request Packet
453 was executed. See the EFI SCSI I/O Protocol in the
454 UEFI Specification for details on the possible
455 return values.
456 @param[out] TargetStatus The status returned by the SCSI target specified
457 by ScsiIo when the SCSI Request Packet was executed
458 on the SCSI Host Controller. See the EFI SCSI
459 I/O Protocol in the UEFI Specification for details
460 on the possible return values.
461 @param[in, out] DataBuffer A pointer to data that was generated by the
462 execution of the SCSI Request Packet. This
463 buffer must be allocated by the caller. If
464 DataLength is 0, then this parameter is optional
465 and may be NULL.
466 @param[in, out] DataLength On input, a pointer to the length in bytes of
467 the DataBuffer buffer. On output, a pointer
468 to the number of bytes written to the DataBuffer
469 buffer.
470 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
471 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
472 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
473
474 @retval EFI_SUCCESS The command was executed successfully.
475 See HostAdapterStatus, TargetStatus, SenseDataLength,
476 and SenseData in that order for additional status information.
477 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
478 entire DataBuffer could not be transferred.
479 The actual number of bytes transferred is returned
480 in DataLength.
481 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
482 there are too many SCSI Command Packets already queued.
483 The SCSI Request Packet was not sent, so no additional
484 status information is available. The caller may retry
485 again later.
486 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
487 SCSI Request Packet. See HostAdapterStatus, TargetStatus,
488 SenseDataLength, and SenseData in that order for
489 additional status information.
490 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
491 is not supported by the SCSI initiator(i.e., SCSI
492 Host Controller). The SCSI Request Packet was not
493 sent, so no additional status information is available.
494 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
495 Request Packet to execute. See HostAdapterStatus,
496 TargetStatus, SenseDataLength, and SenseData in that
497 order for additional status information.
498 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
499
500 **/
501 EFI_STATUS
502 EFIAPI
503 ScsiModeSense10Command (
504 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
505 IN UINT64 Timeout,
506 IN OUT VOID *SenseData, OPTIONAL
507 IN OUT UINT8 *SenseDataLength,
508 OUT UINT8 *HostAdapterStatus,
509 OUT UINT8 *TargetStatus,
510 IN OUT VOID *DataBuffer, OPTIONAL
511 IN OUT UINT32 *DataLength,
512 IN UINT8 DBDField, OPTIONAL
513 IN UINT8 PageControl,
514 IN UINT8 PageCode
515 )
516 {
517 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
518 EFI_STATUS Status;
519 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
520
521 ASSERT (SenseDataLength != NULL);
522 ASSERT (HostAdapterStatus != NULL);
523 ASSERT (TargetStatus != NULL);
524 ASSERT (DataLength != NULL);
525 ASSERT (ScsiIo != NULL);
526
527 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
528 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
529
530 CommandPacket.Timeout = Timeout;
531 CommandPacket.InDataBuffer = DataBuffer;
532 CommandPacket.SenseData = SenseData;
533 CommandPacket.InTransferLength= *DataLength;
534 CommandPacket.Cdb = Cdb;
535 //
536 // Fill Cdb for Mode Sense (10) Command
537 //
538 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
539 //
540 // DBDField is in Cdb[1] bit3 of (bit7..0)
541 //
542 Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);
543 //
544 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
545 //
546 Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));
547 Cdb[7] = (UINT8) (*DataLength >> 8);
548 Cdb[8] = (UINT8) (*DataLength);
549
550 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
551 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
552 CommandPacket.SenseDataLength = *SenseDataLength;
553
554 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
555
556 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
557 *TargetStatus = CommandPacket.TargetStatus;
558 *SenseDataLength = CommandPacket.SenseDataLength;
559 *DataLength = CommandPacket.InTransferLength;
560
561 return Status;
562 }
563
564
565 /**
566 Execute Request Sense SCSI command on a specific SCSI target.
567
568 Executes the Request Sense command on the SCSI target specified by ScsiIo.
569 If Timeout is zero, then this function waits indefinitely for the command to complete.
570 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
571 If ScsiIo is NULL, then ASSERT().
572 If SenseDataLength is NULL, then ASSERT().
573 If HostAdapterStatus is NULL, then ASSERT().
574 If TargetStatus is NULL, then ASSERT().
575
576 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
577 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
578 gets returned.
579
580 @param[in] ScsiIo A pointer to SCSI IO protocol.
581 @param[in] Timeout The length of timeout period.
582 @param[in, out] SenseData A pointer to output sense data.
583 @param[in, out] SenseDataLength The length of output sense data.
584 @param[out] HostAdapterStatus The status of Host Adapter.
585 @param[out] TargetStatus The status of the target.
586
587 @retval EFI_SUCCESS Command is executed successfully.
588 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
589 too many SCSI Command Packets already queued.
590 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
591 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
592 the SCSI initiator(i.e., SCSI Host Controller)
593 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
594 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
595
596 **/
597 EFI_STATUS
598 EFIAPI
599 ScsiRequestSenseCommand (
600 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
601 IN UINT64 Timeout,
602 IN OUT VOID *SenseData, OPTIONAL
603 IN OUT UINT8 *SenseDataLength,
604 OUT UINT8 *HostAdapterStatus,
605 OUT UINT8 *TargetStatus
606 )
607 {
608 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
609 EFI_STATUS Status;
610 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
611
612 ASSERT (SenseDataLength != NULL);
613 ASSERT (HostAdapterStatus != NULL);
614 ASSERT (TargetStatus != NULL);
615 ASSERT (ScsiIo != NULL);
616
617 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
618 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
619
620 CommandPacket.Timeout = Timeout;
621 CommandPacket.InDataBuffer = SenseData;
622 CommandPacket.SenseData = NULL;
623 CommandPacket.InTransferLength= *SenseDataLength;
624 CommandPacket.Cdb = Cdb;
625 //
626 // Fill Cdb for Request Sense Command
627 //
628 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
629 Cdb[4] = (UINT8) (*SenseDataLength);
630
631 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
632 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
633 CommandPacket.SenseDataLength = 0;
634
635 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
636
637 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
638 *TargetStatus = CommandPacket.TargetStatus;
639 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
640
641 return Status;
642 }
643
644
645 /**
646 Execute Read Capacity SCSI command on a specific SCSI target.
647
648 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
649 If Timeout is zero, then this function waits indefinitely for the command to complete.
650 If Timeout is greater than zero, then the command is executed and will timeout after
651 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
652 If ScsiIo is NULL, then ASSERT().
653 If SenseDataLength is NULL, then ASSERT().
654 If HostAdapterStatus is NULL, then ASSERT().
655 If TargetStatus is NULL, then ASSERT().
656 If DataLength is NULL, then ASSERT().
657
658 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
659 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
660 gets returned.
661
662 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
663 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
664 gets returned.
665
666 @param[in] ScsiIo A pointer to SCSI IO protocol.
667 @param[in] Timeout The length of timeout period.
668 @param[in, out] SenseData A pointer to output sense data.
669 @param[in, out] SenseDataLength The length of output sense data.
670 @param[out] HostAdapterStatus The status of Host Adapter.
671 @param[out] TargetStatus The status of the target.
672 @param[in, out] DataBuffer A pointer to a data buffer.
673 @param[in, out] DataLength The length of data buffer.
674 @param[in] Pmi Partial medium indicator.
675
676 @retval EFI_SUCCESS Command is executed successfully.
677 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
678 DataBuffer could not be transferred. The actual
679 number of bytes transferred is returned in DataLength.
680 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
681 there are too many SCSI Command Packets already queued.
682 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
683 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
684 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
685 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
686 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
687
688 **/
689 EFI_STATUS
690 EFIAPI
691 ScsiReadCapacityCommand (
692 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
693 IN UINT64 Timeout,
694 IN OUT VOID *SenseData, OPTIONAL
695 IN OUT UINT8 *SenseDataLength,
696 OUT UINT8 *HostAdapterStatus,
697 OUT UINT8 *TargetStatus,
698 IN OUT VOID *DataBuffer, OPTIONAL
699 IN OUT UINT32 *DataLength,
700 IN BOOLEAN Pmi
701 )
702 {
703 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
704 EFI_STATUS Status;
705 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
706
707 ASSERT (SenseDataLength != NULL);
708 ASSERT (HostAdapterStatus != NULL);
709 ASSERT (TargetStatus != NULL);
710 ASSERT (DataLength != NULL);
711 ASSERT (ScsiIo != NULL);
712
713 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
714 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
715
716 CommandPacket.Timeout = Timeout;
717 CommandPacket.InDataBuffer = DataBuffer;
718 CommandPacket.SenseData = SenseData;
719 CommandPacket.InTransferLength= *DataLength;
720 CommandPacket.Cdb = Cdb;
721 //
722 // Fill Cdb for Read Capacity Command
723 //
724 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
725 if (!Pmi) {
726 //
727 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
728 //
729 ZeroMem ((Cdb + 2), 4);
730 } else {
731 Cdb[8] |= 0x01;
732 }
733
734 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
735 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
736 CommandPacket.SenseDataLength = *SenseDataLength;
737
738 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
739
740 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
741 *TargetStatus = CommandPacket.TargetStatus;
742 *SenseDataLength = CommandPacket.SenseDataLength;
743 *DataLength = CommandPacket.InTransferLength;
744
745 return Status;
746 }
747
748
749 /**
750 Execute Read Capacity SCSI 16 command on a specific SCSI target.
751
752 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
753 If Timeout is zero, then this function waits indefinitely for the command to complete.
754 If Timeout is greater than zero, then the command is executed and will timeout after
755 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
756 If ScsiIo is NULL, then ASSERT().
757 If SenseDataLength is NULL, then ASSERT().
758 If HostAdapterStatus is NULL, then ASSERT().
759 If TargetStatus is NULL, then ASSERT().
760 If DataLength is NULL, then ASSERT().
761
762 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
763 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
764 gets returned.
765
766 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
767 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
768 gets returned.
769
770 @param[in] ScsiIo A pointer to SCSI IO protocol.
771 @param[in] Timeout The length of timeout period.
772 @param[in, out] SenseData A pointer to output sense data.
773 @param[in, out] SenseDataLength The length of output sense data.
774 @param[out] HostAdapterStatus The status of Host Adapter.
775 @param[out] TargetStatus The status of the target.
776 @param[in, out] DataBuffer A pointer to a data buffer.
777 @param[in, out] DataLength The length of data buffer.
778 @param[in] Pmi Partial medium indicator.
779
780 @retval EFI_SUCCESS Command is executed successfully.
781 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
782 DataBuffer could not be transferred. The actual
783 number of bytes transferred is returned in DataLength.
784 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
785 there are too many SCSI Command Packets already queued.
786 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
787 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
788 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
789 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
790 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
791
792 **/
793 EFI_STATUS
794 EFIAPI
795 ScsiReadCapacity16Command (
796 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
797 IN UINT64 Timeout,
798 IN OUT VOID *SenseData, OPTIONAL
799 IN OUT UINT8 *SenseDataLength,
800 OUT UINT8 *HostAdapterStatus,
801 OUT UINT8 *TargetStatus,
802 IN OUT VOID *DataBuffer, OPTIONAL
803 IN OUT UINT32 *DataLength,
804 IN BOOLEAN Pmi
805 )
806 {
807 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
808 EFI_STATUS Status;
809 UINT8 Cdb[16];
810
811 ASSERT (SenseDataLength != NULL);
812 ASSERT (HostAdapterStatus != NULL);
813 ASSERT (TargetStatus != NULL);
814 ASSERT (DataLength != NULL);
815 ASSERT (ScsiIo != NULL);
816
817 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
818 ZeroMem (Cdb, 16);
819
820 CommandPacket.Timeout = Timeout;
821 CommandPacket.InDataBuffer = DataBuffer;
822 CommandPacket.SenseData = SenseData;
823 CommandPacket.InTransferLength= *DataLength;
824 CommandPacket.Cdb = Cdb;
825 //
826 // Fill Cdb for Read Capacity Command
827 //
828 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
829 Cdb[1] = 0x10;
830 if (!Pmi) {
831 //
832 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
833 //
834 ZeroMem ((Cdb + 2), 8);
835 } else {
836 Cdb[14] |= 0x01;
837 }
838
839 Cdb[13] = 0x20;
840 CommandPacket.CdbLength = 16;
841 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
842 CommandPacket.SenseDataLength = *SenseDataLength;
843
844 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
845
846 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
847 *TargetStatus = CommandPacket.TargetStatus;
848 *SenseDataLength = CommandPacket.SenseDataLength;
849 *DataLength = CommandPacket.InTransferLength;
850
851 return Status;
852 }
853
854
855 /**
856 Execute Read(10) SCSI command on a specific SCSI target.
857
858 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
859 If Timeout is zero, then this function waits indefinitely for the command to complete.
860 If Timeout is greater than zero, then the command is executed and will timeout
861 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
862 construct the CDB for this SCSI command.
863 If ScsiIo is NULL, then ASSERT().
864 If SenseDataLength is NULL, then ASSERT().
865 If HostAdapterStatus is NULL, then ASSERT().
866 If TargetStatus is NULL, then ASSERT().
867 If DataLength is NULL, then ASSERT().
868
869 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
870 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
871 gets returned.
872
873 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
874 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
875 gets returned.
876
877 @param[in] ScsiIo A pointer to SCSI IO protocol.
878 @param[in] Timeout The length of timeout period.
879 @param[in, out] SenseData A pointer to output sense data.
880 @param[in, out] SenseDataLength The length of output sense data.
881 @param[out] HostAdapterStatus The status of Host Adapter.
882 @param[out] TargetStatus The status of the target.
883 @param[in, out] DataBuffer Read 10 command data.
884 @param[in, out] DataLength The length of data buffer.
885 @param[in] StartLba The start address of LBA.
886 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
887
888 @retval EFI_SUCCESS Command is executed successfully.
889 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
890 not be transferred. The actual number of bytes transferred is returned in DataLength.
891 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
892 SCSI Command Packets already queued.
893 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
894 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
895 the SCSI initiator(i.e., SCSI Host Controller)
896 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
897 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
898
899 **/
900 EFI_STATUS
901 EFIAPI
902 ScsiRead10Command (
903 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
904 IN UINT64 Timeout,
905 IN OUT VOID *SenseData, OPTIONAL
906 IN OUT UINT8 *SenseDataLength,
907 OUT UINT8 *HostAdapterStatus,
908 OUT UINT8 *TargetStatus,
909 IN OUT VOID *DataBuffer, OPTIONAL
910 IN OUT UINT32 *DataLength,
911 IN UINT32 StartLba,
912 IN UINT32 SectorSize
913 )
914 {
915 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
916 EFI_STATUS Status;
917 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
918
919 ASSERT (SenseDataLength != NULL);
920 ASSERT (HostAdapterStatus != NULL);
921 ASSERT (TargetStatus != NULL);
922 ASSERT (DataLength != NULL);
923 ASSERT (ScsiIo != NULL);
924
925 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
926 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
927
928 CommandPacket.Timeout = Timeout;
929 CommandPacket.InDataBuffer = DataBuffer;
930 CommandPacket.SenseData = SenseData;
931 CommandPacket.InTransferLength= *DataLength;
932 CommandPacket.Cdb = Cdb;
933 //
934 // Fill Cdb for Read (10) Command
935 //
936 Cdb[0] = EFI_SCSI_OP_READ10;
937 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
938 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
939
940 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
941 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
942 CommandPacket.SenseDataLength = *SenseDataLength;
943
944 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
945
946 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
947 *TargetStatus = CommandPacket.TargetStatus;
948 *SenseDataLength = CommandPacket.SenseDataLength;
949 *DataLength = CommandPacket.InTransferLength;
950
951 return Status;
952 }
953
954
955 /**
956 Execute Write(10) SCSI command on a specific SCSI target.
957
958 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
959 If Timeout is zero, then this function waits indefinitely for the command to complete.
960 If Timeout is greater than zero, then the command is executed and will timeout after
961 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
962 the CDB for this SCSI command.
963 If ScsiIo is NULL, then ASSERT().
964 If SenseDataLength is NULL, then ASSERT().
965 If HostAdapterStatus is NULL, then ASSERT().
966 If TargetStatus is NULL, then ASSERT().
967 If DataLength is NULL, then ASSERT().
968
969 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
970 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
971 gets returned.
972
973 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
974 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
975 gets returned.
976
977 @param[in] ScsiIo SCSI IO Protocol to use
978 @param[in] Timeout The length of timeout period.
979 @param[in, out] SenseData A pointer to output sense data.
980 @param[in, out] SenseDataLength The length of output sense data.
981 @param[out] HostAdapterStatus The status of Host Adapter.
982 @param[out] TargetStatus The status of the target.
983 @param[in, out] DataBuffer A pointer to a data buffer.
984 @param[in, out] DataLength The length of data buffer.
985 @param[in] StartLba The start address of LBA.
986 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
987
988 @retval EFI_SUCCESS Command is executed successfully.
989 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
990 not be transferred. The actual number of bytes transferred is returned in DataLength.
991 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
992 SCSI Command Packets already queued.
993 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
994 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
995 the SCSI initiator(i.e., SCSI Host Controller)
996 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
997 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
998
999 **/
1000 EFI_STATUS
1001 EFIAPI
1002 ScsiWrite10Command (
1003 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1004 IN UINT64 Timeout,
1005 IN OUT VOID *SenseData, OPTIONAL
1006 IN OUT UINT8 *SenseDataLength,
1007 OUT UINT8 *HostAdapterStatus,
1008 OUT UINT8 *TargetStatus,
1009 IN OUT VOID *DataBuffer, OPTIONAL
1010 IN OUT UINT32 *DataLength,
1011 IN UINT32 StartLba,
1012 IN UINT32 SectorSize
1013 )
1014 {
1015 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1016 EFI_STATUS Status;
1017 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
1018
1019 ASSERT (SenseDataLength != NULL);
1020 ASSERT (HostAdapterStatus != NULL);
1021 ASSERT (TargetStatus != NULL);
1022 ASSERT (DataLength != NULL);
1023 ASSERT (ScsiIo != NULL);
1024
1025 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1026 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
1027
1028 CommandPacket.Timeout = Timeout;
1029 CommandPacket.OutDataBuffer = DataBuffer;
1030 CommandPacket.SenseData = SenseData;
1031 CommandPacket.OutTransferLength= *DataLength;
1032 CommandPacket.Cdb = Cdb;
1033 //
1034 // Fill Cdb for Write (10) Command
1035 //
1036 Cdb[0] = EFI_SCSI_OP_WRITE10;
1037 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
1038 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
1039
1040 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
1041 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
1042 CommandPacket.SenseDataLength = *SenseDataLength;
1043
1044 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1045
1046 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1047 *TargetStatus = CommandPacket.TargetStatus;
1048 *SenseDataLength = CommandPacket.SenseDataLength;
1049 *DataLength = CommandPacket.OutTransferLength;
1050
1051 return Status;
1052 }
1053
1054 /**
1055 Execute Read(16) SCSI command on a specific SCSI target.
1056
1057 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
1058 If Timeout is zero, then this function waits indefinitely for the command to complete.
1059 If Timeout is greater than zero, then the command is executed and will timeout
1060 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
1061 construct the CDB for this SCSI command.
1062 If ScsiIo is NULL, then ASSERT().
1063 If SenseDataLength is NULL, then ASSERT().
1064 If HostAdapterStatus is NULL, then ASSERT().
1065 If TargetStatus is NULL, then ASSERT().
1066 If DataLength is NULL, then ASSERT().
1067
1068 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
1069 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1070 gets returned.
1071
1072 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
1073 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1074 gets returned.
1075
1076 @param[in] ScsiIo A pointer to SCSI IO protocol.
1077 @param[in] Timeout The length of timeout period.
1078 @param[in, out] SenseData A pointer to output sense data.
1079 @param[in, out] SenseDataLength The length of output sense data.
1080 @param[out] HostAdapterStatus The status of Host Adapter.
1081 @param[out] TargetStatus The status of the target.
1082 @param[in, out] DataBuffer Read 16 command data.
1083 @param[in, out] DataLength The length of data buffer.
1084 @param[in] StartLba The start address of LBA.
1085 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
1086
1087 @retval EFI_SUCCESS Command is executed successfully.
1088 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
1089 not be transferred. The actual number of bytes transferred is returned in DataLength.
1090 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
1091 SCSI Command Packets already queued.
1092 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
1093 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
1094 the SCSI initiator(i.e., SCSI Host Controller)
1095 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1096 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
1097
1098 **/
1099 EFI_STATUS
1100 EFIAPI
1101 ScsiRead16Command (
1102 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1103 IN UINT64 Timeout,
1104 IN OUT VOID *SenseData, OPTIONAL
1105 IN OUT UINT8 *SenseDataLength,
1106 OUT UINT8 *HostAdapterStatus,
1107 OUT UINT8 *TargetStatus,
1108 IN OUT VOID *DataBuffer, OPTIONAL
1109 IN OUT UINT32 *DataLength,
1110 IN UINT64 StartLba,
1111 IN UINT32 SectorSize
1112 )
1113 {
1114 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1115 EFI_STATUS Status;
1116 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
1117
1118 ASSERT (SenseDataLength != NULL);
1119 ASSERT (HostAdapterStatus != NULL);
1120 ASSERT (TargetStatus != NULL);
1121 ASSERT (DataLength != NULL);
1122 ASSERT (ScsiIo != NULL);
1123
1124 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1125 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
1126
1127 CommandPacket.Timeout = Timeout;
1128 CommandPacket.InDataBuffer = DataBuffer;
1129 CommandPacket.SenseData = SenseData;
1130 CommandPacket.InTransferLength = *DataLength;
1131 CommandPacket.Cdb = Cdb;
1132 //
1133 // Fill Cdb for Read (16) Command
1134 //
1135 Cdb[0] = EFI_SCSI_OP_READ16;
1136 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
1137 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
1138
1139 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
1140 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
1141 CommandPacket.SenseDataLength = *SenseDataLength;
1142
1143 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1144
1145 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1146 *TargetStatus = CommandPacket.TargetStatus;
1147 *SenseDataLength = CommandPacket.SenseDataLength;
1148 *DataLength = CommandPacket.InTransferLength;
1149
1150 return Status;
1151 }
1152
1153
1154 /**
1155 Execute Write(16) SCSI command on a specific SCSI target.
1156
1157 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
1158 If Timeout is zero, then this function waits indefinitely for the command to complete.
1159 If Timeout is greater than zero, then the command is executed and will timeout after
1160 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
1161 the CDB for this SCSI command.
1162 If ScsiIo is NULL, then ASSERT().
1163 If SenseDataLength is NULL, then ASSERT().
1164 If HostAdapterStatus is NULL, then ASSERT().
1165 If TargetStatus is NULL, then ASSERT().
1166 If DataLength is NULL, then ASSERT().
1167
1168 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
1169 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1170 gets returned.
1171
1172 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
1173 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1174 gets returned.
1175
1176 @param[in] ScsiIo SCSI IO Protocol to use
1177 @param[in] Timeout The length of timeout period.
1178 @param[in, out] SenseData A pointer to output sense data.
1179 @param[in, out] SenseDataLength The length of output sense data.
1180 @param[out] HostAdapterStatus The status of Host Adapter.
1181 @param[out] TargetStatus The status of the target.
1182 @param[in, out] DataBuffer A pointer to a data buffer.
1183 @param[in, out] DataLength The length of data buffer.
1184 @param[in] StartLba The start address of LBA.
1185 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
1186
1187 @retval EFI_SUCCESS Command is executed successfully.
1188 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
1189 not be transferred. The actual number of bytes transferred is returned in DataLength.
1190 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
1191 SCSI Command Packets already queued.
1192 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
1193 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
1194 the SCSI initiator(i.e., SCSI Host Controller)
1195 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1196 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
1197
1198 **/
1199 EFI_STATUS
1200 EFIAPI
1201 ScsiWrite16Command (
1202 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1203 IN UINT64 Timeout,
1204 IN OUT VOID *SenseData, OPTIONAL
1205 IN OUT UINT8 *SenseDataLength,
1206 OUT UINT8 *HostAdapterStatus,
1207 OUT UINT8 *TargetStatus,
1208 IN OUT VOID *DataBuffer, OPTIONAL
1209 IN OUT UINT32 *DataLength,
1210 IN UINT64 StartLba,
1211 IN UINT32 SectorSize
1212 )
1213 {
1214 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1215 EFI_STATUS Status;
1216 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
1217
1218 ASSERT (SenseDataLength != NULL);
1219 ASSERT (HostAdapterStatus != NULL);
1220 ASSERT (TargetStatus != NULL);
1221 ASSERT (DataLength != NULL);
1222 ASSERT (ScsiIo != NULL);
1223
1224 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1225 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
1226
1227 CommandPacket.Timeout = Timeout;
1228 CommandPacket.OutDataBuffer = DataBuffer;
1229 CommandPacket.SenseData = SenseData;
1230 CommandPacket.OutTransferLength = *DataLength;
1231 CommandPacket.Cdb = Cdb;
1232 //
1233 // Fill Cdb for Write (16) Command
1234 //
1235 Cdb[0] = EFI_SCSI_OP_WRITE16;
1236 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
1237 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
1238
1239 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
1240 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
1241 CommandPacket.SenseDataLength = *SenseDataLength;
1242
1243 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1244
1245 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1246 *TargetStatus = CommandPacket.TargetStatus;
1247 *SenseDataLength = CommandPacket.SenseDataLength;
1248 *DataLength = CommandPacket.OutTransferLength;
1249
1250 return Status;
1251 }