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