]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
434640ccd08b30c0b119ab8456e604d63ab4fd8f
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
1 /** @file
2 UEFI SCSI Library implementation
3
4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. 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/DebugLib.h>
18 #include <Library/UefiScsiLib.h>
19 #include <Library/BaseMemoryLib.h>
20
21 #include <IndustryStandard/Scsi.h>
22
23
24 //
25 // Max bytes needed to represent ID of a SCSI device
26 //
27 #define EFI_SCSI_TARGET_MAX_BYTES (0x10)
28
29 //
30 // bit5..7 are for Logical unit number
31 // 11100000b (0xe0)
32 //
33 #define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0
34
35 //
36 // Scsi Command Length six or ten
37 //
38 #define EFI_SCSI_OP_LENGTH_SIX 0x6
39 #define EFI_SCSI_OP_LENGTH_TEN 0xa
40
41
42
43 /**
44 Execute Test Unit Ready SCSI command on a specific SCSI target.
45
46 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.
47 If Timeout is zero, then this function waits indefinitely for the command to complete.
48 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
49 If ScsiIo is NULL, then ASSERT().
50 If SenseDataLength is NULL, then ASSERT().
51 If HostAdapterStatus is NULL, then ASSERT().
52 If TargetStatus is NULL, then ASSERT().
53
54
55 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
56 for the specific SCSI target.
57 @param[in] Timeout The timeout in 100 ns units to use for the execution
58 of this SCSI Request Packet. A Timeout value of
59 zero means that this function will wait indefinitely
60 for the SCSI Request Packet to execute. If Timeout
61 is greater than zero, then this function will return
62 EFI_TIMEOUT if the time required to execute the SCSI
63 Request Packet is greater than Timeout.
64 @param[in, out] SenseData A pointer to sense data that was generated by
65 the execution of the SCSI Request Packet. This
66 buffer must be allocated by the caller.
67 If SenseDataLength is 0, then this parameter is
68 optional and may be NULL.
69 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of
70 the SenseData buffer. On output, a pointer to
71 the number of bytes written to the SenseData buffer.
72 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces
73 the SCSI bus containing the SCSI target specified by
74 ScsiIo when the SCSI Request Packet was executed.
75 See the EFI SCSI I/O Protocol in the UEFI Specification
76 for details on the possible return values.
77 @param[out] TargetStatus The status returned by the SCSI target specified
78 by ScsiIo when the SCSI Request Packet was executed
79 on the SCSI Host Controller. See the EFI SCSI I/O
80 Protocol in the UEFI Specification for details on
81 the possible return values.
82
83 @retval EFI_SUCCESS The command was executed successfully.
84 See HostAdapterStatus, TargetStatus, SenseDataLength,
85 and SenseData in that order for additional status
86 information.
87 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
88 there are too many SCSI Command Packets already
89 queued. The SCSI Request Packet was not sent, so
90 no additional status information is available.
91 The caller may retry again later.
92 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
93 SCSI Request Packet. See HostAdapterStatus,
94 TargetStatus, SenseDataLength, and SenseData in that
95 order for additional status information.
96 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
97 is not supported by the SCSI initiator(i.e., SCSI
98 Host Controller). The SCSI Request Packet was not
99 sent, so no additional status information is available.
100 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
101 Packet to execute. See HostAdapterStatus, TargetStatus,
102 SenseDataLength, and SenseData in that order for
103 additional status information.
104
105 **/
106 EFI_STATUS
107 EFIAPI
108 ScsiTestUnitReadyCommand (
109 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
110 IN UINT64 Timeout,
111 IN OUT VOID *SenseData, OPTIONAL
112 IN OUT UINT8 *SenseDataLength,
113 OUT UINT8 *HostAdapterStatus,
114 OUT UINT8 *TargetStatus
115 )
116 {
117 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
118 EFI_STATUS Status;
119 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
120
121 ASSERT (SenseDataLength != NULL);
122 ASSERT (HostAdapterStatus != NULL);
123 ASSERT (TargetStatus != NULL);
124 ASSERT (ScsiIo != NULL);
125
126 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
127 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
128
129 CommandPacket.Timeout = Timeout;
130 CommandPacket.InDataBuffer = NULL;
131 CommandPacket.InTransferLength= 0;
132 CommandPacket.OutDataBuffer = NULL;
133 CommandPacket.OutTransferLength= 0;
134 CommandPacket.SenseData = SenseData;
135 CommandPacket.Cdb = Cdb;
136 //
137 // Fill Cdb for Test Unit Ready Command
138 //
139 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
140 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
141 CommandPacket.SenseDataLength = *SenseDataLength;
142
143 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
144
145 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
146 *TargetStatus = CommandPacket.TargetStatus;
147 *SenseDataLength = CommandPacket.SenseDataLength;
148
149 return Status;
150 }
151
152
153 /**
154 Execute Inquiry SCSI command on a specific SCSI target.
155
156 Executes the Inquiry command on the SCSI target specified by ScsiIo.
157 If Timeout is zero, then this function waits indefinitely for the command to complete.
158 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
159 If ScsiIo is NULL, then ASSERT().
160 If SenseDataLength is NULL, then ASSERT().
161 If HostAdapterStatus is NULL, then ASSERT().
162 If TargetStatus is NULL, then ASSERT().
163 If InquiryDataLength is NULL, then ASSERT().
164
165 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
166 for the specific SCSI target.
167 @param[in] Timeout The timeout in 100 ns units to use for the
168 execution of this SCSI Request Packet. A Timeout
169 value of zero means that this function will wait
170 indefinitely for the SCSI Request Packet to execute.
171 If Timeout is greater than zero, then this function
172 will return EFI_TIMEOUT if the time required to
173 execute the SCSI Request Packet is greater than Timeout.
174 @param[in, out] SenseData A pointer to sense data that was generated
175 by the execution of the SCSI Request Packet.
176 This buffer must be allocated by the caller.
177 If SenseDataLength is 0, then this parameter
178 is optional and may be NULL.
179 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
180 On output, the number of bytes written to the SenseData buffer.
181 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
182 produces the SCSI bus containing the SCSI
183 target specified by ScsiIo when the SCSI
184 Request Packet was executed. See the EFI
185 SCSI I/O Protocol in the UEFI Specification
186 for details on the possible return values.
187 @param[out] TargetStatus The status returned by the SCSI target specified
188 by ScsiIo when the SCSI Request Packet was
189 executed on the SCSI Host Controller.
190 See the EFI SCSI I/O Protocol in the UEFI
191 Specification for details on the possible
192 return values.
193 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
194 by the execution of the SCSI Request Packet.
195 This buffer must be allocated by the caller.
196 If InquiryDataLength is 0, then this parameter
197 is optional and may be NULL.
198 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
199 of the InquiryDataBuffer buffer.
200 On output, a pointer to the number of bytes
201 written to the InquiryDataBuffer buffer.
202 @param[in] EnableVitalProductData If TRUE, then the supported vital product
203 data is returned in InquiryDataBuffer.
204 If FALSE, then the standard inquiry data is
205 returned in InquiryDataBuffer.
206
207 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
208 TargetStatus, SenseDataLength, and SenseData in that order
209 for additional status information.
210 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
211 InquiryDataBuffer could not be transferred. The actual
212 number of bytes transferred is returned in InquiryDataLength.
213 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
214 are too many SCSI Command Packets already queued.
215 The SCSI Request Packet was not sent, so no additional
216 status information is available. The caller may retry again later.
217 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
218 Request Packet. See HostAdapterStatus, TargetStatus,
219 SenseDataLength, and SenseData in that order for additional
220 status information.
221 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
222 supported by the SCSI initiator(i.e., SCSI Host Controller).
223 The SCSI Request Packet was not sent, so no additional
224 status information is available.
225 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
226 Packet to execute. See HostAdapterStatus, TargetStatus,
227 SenseDataLength, and SenseData in that order for
228 additional status information.
229
230 **/
231 EFI_STATUS
232 EFIAPI
233 ScsiInquiryCommand (
234 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
235 IN UINT64 Timeout,
236 IN OUT VOID *SenseData, OPTIONAL
237 IN OUT UINT8 *SenseDataLength,
238 OUT UINT8 *HostAdapterStatus,
239 OUT UINT8 *TargetStatus,
240 IN OUT VOID *InquiryDataBuffer, OPTIONAL
241 IN OUT UINT32 *InquiryDataLength,
242 IN BOOLEAN EnableVitalProductData
243 )
244 {
245 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
246 EFI_STATUS Status;
247 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
248
249 ASSERT (SenseDataLength != NULL);
250 ASSERT (HostAdapterStatus != NULL);
251 ASSERT (TargetStatus != NULL);
252 ASSERT (InquiryDataLength != NULL);
253 ASSERT (ScsiIo != NULL);
254
255 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
256 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
257
258 CommandPacket.Timeout = Timeout;
259 CommandPacket.InDataBuffer = InquiryDataBuffer;
260 CommandPacket.InTransferLength= *InquiryDataLength;
261 CommandPacket.SenseData = SenseData;
262 CommandPacket.SenseDataLength = *SenseDataLength;
263 CommandPacket.Cdb = Cdb;
264
265 Cdb[0] = EFI_SCSI_OP_INQUIRY;
266 if (EnableVitalProductData) {
267 Cdb[1] |= 0x01;
268 }
269
270 if (*InquiryDataLength > 0xff) {
271 *InquiryDataLength = 0xff;
272 }
273
274 Cdb[4] = (UINT8) (*InquiryDataLength);
275 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
276 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
277
278 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
279
280 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
281 *TargetStatus = CommandPacket.TargetStatus;
282 *SenseDataLength = CommandPacket.SenseDataLength;
283 *InquiryDataLength = CommandPacket.InTransferLength;
284
285 return Status;
286 }
287
288
289 /**
290 Execute Mode Sense(10) SCSI command on a specific SCSI target.
291
292 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
293 If Timeout is zero, then this function waits indefinitely for the command to complete.
294 If Timeout is greater than zero, then the command is executed and will timeout
295 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
296 are used to construct the CDB for this SCSI command.
297 If ScsiIo is NULL, then ASSERT().
298 If SenseDataLength is NULL, then ASSERT().
299 If HostAdapterStatus is NULL, then ASSERT().
300 If TargetStatus is NULL, then ASSERT().
301 If DataLength is NULL, then ASSERT().
302
303
304 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
305 for the specific SCSI target.
306 @param[in] Timeout The timeout in 100 ns units to use for the
307 execution of this SCSI Request Packet. A Timeout
308 value of zero means that this function will wait
309 indefinitely for the SCSI Request Packet to execute.
310 If Timeout is greater than zero, then this function
311 will return EFI_TIMEOUT if the time required to
312 execute the SCSI Request Packet is greater than Timeout.
313 @param[in, out] SenseData A pointer to sense data that was generated
314 by the execution of the SCSI Request Packet.
315 This buffer must be allocated by the caller.
316 If SenseDataLength is 0, then this parameter
317 is optional and may be NULL.
318 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
319 On output, the number of bytes written to the SenseData buffer.
320 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
321 produces the SCSI bus containing the SCSI target
322 specified by ScsiIo when the SCSI Request Packet
323 was executed. See the EFI SCSI I/O Protocol in the
324 UEFI Specification for details on the possible
325 return values.
326 @param[out] TargetStatus The status returned by the SCSI target specified
327 by ScsiIo when the SCSI Request Packet was executed
328 on the SCSI Host Controller. See the EFI SCSI
329 I/O Protocol in the UEFI Specification for details
330 on the possible return values.
331 @param[in, out] DataBuffer A pointer to data that was generated by the
332 execution of the SCSI Request Packet. This
333 buffer must be allocated by the caller. If
334 DataLength is 0, then this parameter is optional
335 and may be NULL.
336 @param[in, out] DataLength On input, a pointer to the length in bytes of
337 the DataBuffer buffer. On output, a pointer
338 to the number of bytes written to the DataBuffer
339 buffer.
340 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
341 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
342 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
343
344 @retval EFI_SUCCESS The command was executed successfully.
345 See HostAdapterStatus, TargetStatus, SenseDataLength,
346 and SenseData in that order for additional status information.
347 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
348 entire DataBuffer could not be transferred.
349 The actual number of bytes transferred is returned
350 in DataLength.
351 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
352 there are too many SCSI Command Packets already queued.
353 The SCSI Request Packet was not sent, so no additional
354 status information is available. The caller may retry
355 again later.
356 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
357 SCSI Request Packet. See HostAdapterStatus, TargetStatus,
358 SenseDataLength, and SenseData in that order for
359 additional status information.
360 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
361 is not supported by the SCSI initiator(i.e., SCSI
362 Host Controller). The SCSI Request Packet was not
363 sent, so no additional status information is available.
364 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
365 Request Packet to execute. See HostAdapterStatus,
366 TargetStatus, SenseDataLength, and SenseData in that
367 order for additional status information.
368
369 **/
370 EFI_STATUS
371 EFIAPI
372 ScsiModeSense10Command (
373 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
374 IN UINT64 Timeout,
375 IN OUT VOID *SenseData, OPTIONAL
376 IN OUT UINT8 *SenseDataLength,
377 OUT UINT8 *HostAdapterStatus,
378 OUT UINT8 *TargetStatus,
379 IN OUT VOID *DataBuffer, OPTIONAL
380 IN OUT UINT32 *DataLength,
381 IN UINT8 DBDField, OPTIONAL
382 IN UINT8 PageControl,
383 IN UINT8 PageCode
384 )
385 {
386 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
387 EFI_STATUS Status;
388 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
389
390 ASSERT (SenseDataLength != NULL);
391 ASSERT (HostAdapterStatus != NULL);
392 ASSERT (TargetStatus != NULL);
393 ASSERT (DataLength != NULL);
394 ASSERT (ScsiIo != NULL);
395
396 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
397 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
398
399 CommandPacket.Timeout = Timeout;
400 CommandPacket.InDataBuffer = DataBuffer;
401 CommandPacket.SenseData = SenseData;
402 CommandPacket.InTransferLength= *DataLength;
403 CommandPacket.Cdb = Cdb;
404 //
405 // Fill Cdb for Mode Sense (10) Command
406 //
407 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
408 //
409 // DBDField is in Cdb[1] bit3 of (bit7..0)
410 //
411 Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);
412 //
413 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
414 //
415 Cdb[2] = (UINT8) (((PageControl & 0x3) << 6) | (PageCode & 0x3f));
416 Cdb[7] = (UINT8) (*DataLength >> 8);
417 Cdb[8] = (UINT8) (*DataLength);
418
419 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
420 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
421 CommandPacket.SenseDataLength = *SenseDataLength;
422
423 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
424
425 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
426 *TargetStatus = CommandPacket.TargetStatus;
427 *SenseDataLength = CommandPacket.SenseDataLength;
428 *DataLength = CommandPacket.InTransferLength;
429
430 return Status;
431 }
432
433
434 /**
435 Execute Request Sense SCSI command on a specific SCSI target.
436
437 Executes the Request Sense command on the SCSI target specified by ScsiIo.
438 If Timeout is zero, then this function waits indefinitely for the command to complete.
439 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
440 If ScsiIo is NULL, then ASSERT().
441 If SenseDataLength is NULL, then ASSERT().
442 If HostAdapterStatus is NULL, then ASSERT().
443 If TargetStatus is NULL, then ASSERT().
444
445 @param[in] ScsiIo A pointer to SCSI IO protocol.
446 @param[in] Timeout The length of timeout period.
447 @param[in, out] SenseData A pointer to output sense data.
448 @param[in, out] SenseDataLength The length of output sense data.
449 @param[out] HostAdapterStatus The status of Host Adapter.
450 @param[out] TargetStatus The status of the target.
451
452 @retval EFI_SUCCESS Command is executed successfully.
453 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
454 too many SCSI Command Packets already queued.
455 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
456 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
457 the SCSI initiator(i.e., SCSI Host Controller)
458 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
459
460 **/
461 EFI_STATUS
462 EFIAPI
463 ScsiRequestSenseCommand (
464 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
465 IN UINT64 Timeout,
466 IN OUT VOID *SenseData, OPTIONAL
467 IN OUT UINT8 *SenseDataLength,
468 OUT UINT8 *HostAdapterStatus,
469 OUT UINT8 *TargetStatus
470 )
471 {
472 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
473 EFI_STATUS Status;
474 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
475
476 ASSERT (SenseDataLength != NULL);
477 ASSERT (HostAdapterStatus != NULL);
478 ASSERT (TargetStatus != NULL);
479 ASSERT (ScsiIo != NULL);
480
481 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
482 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
483
484 CommandPacket.Timeout = Timeout;
485 CommandPacket.InDataBuffer = SenseData;
486 CommandPacket.SenseData = NULL;
487 CommandPacket.InTransferLength= *SenseDataLength;
488 CommandPacket.Cdb = Cdb;
489 //
490 // Fill Cdb for Request Sense Command
491 //
492 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
493 Cdb[4] = (UINT8) (*SenseDataLength);
494
495 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
496 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
497 CommandPacket.SenseDataLength = 0;
498
499 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
500
501 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
502 *TargetStatus = CommandPacket.TargetStatus;
503 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
504
505 return Status;
506 }
507
508
509 /**
510 Execute Read Capacity SCSI command on a specific SCSI target.
511
512 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
513 If Timeout is zero, then this function waits indefinitely for the command to complete.
514 If Timeout is greater than zero, then the command is executed and will timeout after
515 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
516 If ScsiIo is NULL, then ASSERT().
517 If SenseDataLength is NULL, then ASSERT().
518 If HostAdapterStatus is NULL, then ASSERT().
519 If TargetStatus is NULL, then ASSERT().
520 If DataLength is NULL, then ASSERT().
521
522 @param[in] ScsiIo A pointer to SCSI IO protocol.
523 @param[in] Timeout The length of timeout period.
524 @param[in, out] SenseData A pointer to output sense data.
525 @param[in, out] SenseDataLength The length of output sense data.
526 @param[out] HostAdapterStatus The status of Host Adapter.
527 @param[out] TargetStatus The status of the target.
528 @param[in, out] DataBuffer A pointer to a data buffer.
529 @param[in, out] DataLength The length of data buffer.
530 @param[in] Pmi Partial medium indicator.
531
532 @retval EFI_SUCCESS Command is executed successfully.
533 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
534 DataBuffer could not be transferred. The actual
535 number of bytes transferred is returned in DataLength.
536 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
537 there are too many SCSI Command Packets already queued.
538 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
539 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
540 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
541 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
542
543 **/
544 EFI_STATUS
545 EFIAPI
546 ScsiReadCapacityCommand (
547 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
548 IN UINT64 Timeout,
549 IN OUT VOID *SenseData, OPTIONAL
550 IN OUT UINT8 *SenseDataLength,
551 OUT UINT8 *HostAdapterStatus,
552 OUT UINT8 *TargetStatus,
553 IN OUT VOID *DataBuffer, OPTIONAL
554 IN OUT UINT32 *DataLength,
555 IN BOOLEAN Pmi
556 )
557 {
558 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
559 EFI_STATUS Status;
560 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
561
562 ASSERT (SenseDataLength != NULL);
563 ASSERT (HostAdapterStatus != NULL);
564 ASSERT (TargetStatus != NULL);
565 ASSERT (DataLength != NULL);
566 ASSERT (ScsiIo != NULL);
567
568 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
569 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
570
571 CommandPacket.Timeout = Timeout;
572 CommandPacket.InDataBuffer = DataBuffer;
573 CommandPacket.SenseData = SenseData;
574 CommandPacket.InTransferLength= *DataLength;
575 CommandPacket.Cdb = Cdb;
576 //
577 // Fill Cdb for Read Capacity Command
578 //
579 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
580 if (!Pmi) {
581 //
582 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
583 //
584 ZeroMem ((Cdb + 2), 4);
585 } else {
586 Cdb[8] |= 0x01;
587 }
588
589 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
590 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
591 CommandPacket.SenseDataLength = *SenseDataLength;
592
593 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
594
595 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
596 *TargetStatus = CommandPacket.TargetStatus;
597 *SenseDataLength = CommandPacket.SenseDataLength;
598 *DataLength = CommandPacket.InTransferLength;
599
600 return Status;
601 }
602
603
604 /**
605 Execute Read Capacity SCSI 16 command on a specific SCSI target.
606
607 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
608 If Timeout is zero, then this function waits indefinitely for the command to complete.
609 If Timeout is greater than zero, then the command is executed and will timeout after
610 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
611 If ScsiIo is NULL, then ASSERT().
612 If SenseDataLength is NULL, then ASSERT().
613 If HostAdapterStatus is NULL, then ASSERT().
614 If TargetStatus is NULL, then ASSERT().
615 If DataLength is NULL, then ASSERT().
616
617 @param[in] ScsiIo A pointer to SCSI IO protocol.
618 @param[in] Timeout The length of timeout period.
619 @param[in, out] SenseData A pointer to output sense data.
620 @param[in, out] SenseDataLength The length of output sense data.
621 @param[out] HostAdapterStatus The status of Host Adapter.
622 @param[out] TargetStatus The status of the target.
623 @param[in, out] DataBuffer A pointer to a data buffer.
624 @param[in, out] DataLength The length of data buffer.
625 @param[in] Pmi Partial medium indicator.
626
627 @retval EFI_SUCCESS Command is executed successfully.
628 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
629 DataBuffer could not be transferred. The actual
630 number of bytes transferred is returned in DataLength.
631 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
632 there are too many SCSI Command Packets already queued.
633 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
634 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
635 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
636 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
637
638 **/
639 EFI_STATUS
640 EFIAPI
641 ScsiReadCapacity16Command (
642 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
643 IN UINT64 Timeout,
644 IN OUT VOID *SenseData, OPTIONAL
645 IN OUT UINT8 *SenseDataLength,
646 OUT UINT8 *HostAdapterStatus,
647 OUT UINT8 *TargetStatus,
648 IN OUT VOID *DataBuffer, OPTIONAL
649 IN OUT UINT32 *DataLength,
650 IN BOOLEAN Pmi
651 )
652 {
653 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
654 EFI_STATUS Status;
655 UINT8 Cdb[16];
656
657 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
658 ZeroMem (Cdb, 16);
659
660 CommandPacket.Timeout = Timeout;
661 CommandPacket.InDataBuffer = DataBuffer;
662 CommandPacket.SenseData = SenseData;
663 CommandPacket.InTransferLength= *DataLength;
664 CommandPacket.Cdb = Cdb;
665 //
666 // Fill Cdb for Read Capacity Command
667 //
668 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
669 Cdb[1] = 0x10;
670 if (!Pmi) {
671 //
672 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
673 //
674 ZeroMem ((Cdb + 2), 8);
675 } else {
676 Cdb[14] |= 0x01;
677 }
678
679 Cdb[13] = 0x20;
680 CommandPacket.CdbLength = 16;
681 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
682 CommandPacket.SenseDataLength = *SenseDataLength;
683
684 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
685
686 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
687 *TargetStatus = CommandPacket.TargetStatus;
688 *SenseDataLength = CommandPacket.SenseDataLength;
689 *DataLength = CommandPacket.InTransferLength;
690
691 return Status;
692 }
693
694
695 /**
696 Execute Read(10) SCSI command on a specific SCSI target.
697
698 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
699 If Timeout is zero, then this function waits indefinitely for the command to complete.
700 If Timeout is greater than zero, then the command is executed and will timeout
701 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
702 construct the CDB for this SCSI command.
703 If ScsiIo is NULL, then ASSERT().
704 If SenseDataLength is NULL, then ASSERT().
705 If HostAdapterStatus is NULL, then ASSERT().
706 If TargetStatus is NULL, then ASSERT().
707 If DataLength is NULL, then ASSERT().
708
709
710 @param[in] ScsiIo A pointer to SCSI IO protocol.
711 @param[in] Timeout The length of timeout period.
712 @param[in, out] SenseData A pointer to output sense data.
713 @param[in, out] SenseDataLength The length of output sense data.
714 @param[out] HostAdapterStatus The status of Host Adapter.
715 @param[out] TargetStatus The status of the target.
716 @param[in, out] DataBuffer Read 10 command data.
717 @param[in, out] DataLength The length of data buffer.
718 @param[in] StartLba The start address of LBA.
719 @param[in] SectorSize The sector size.
720
721 @retval EFI_SUCCESS Command is executed successfully.
722 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
723 not be transferred. The actual number of bytes transferred is returned in DataLength.
724 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
725 SCSI Command Packets already queued.
726 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
727 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
728 the SCSI initiator(i.e., SCSI Host Controller)
729 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
730
731 **/
732 EFI_STATUS
733 EFIAPI
734 ScsiRead10Command (
735 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
736 IN UINT64 Timeout,
737 IN OUT VOID *SenseData, OPTIONAL
738 IN OUT UINT8 *SenseDataLength,
739 OUT UINT8 *HostAdapterStatus,
740 OUT UINT8 *TargetStatus,
741 IN OUT VOID *DataBuffer, OPTIONAL
742 IN OUT UINT32 *DataLength,
743 IN UINT32 StartLba,
744 IN UINT32 SectorSize
745 )
746 {
747 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
748 EFI_STATUS Status;
749 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
750
751 ASSERT (SenseDataLength != NULL);
752 ASSERT (HostAdapterStatus != NULL);
753 ASSERT (TargetStatus != NULL);
754 ASSERT (DataLength != NULL);
755 ASSERT (ScsiIo != NULL);
756
757 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
758 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
759
760 CommandPacket.Timeout = Timeout;
761 CommandPacket.InDataBuffer = DataBuffer;
762 CommandPacket.SenseData = SenseData;
763 CommandPacket.InTransferLength= *DataLength;
764 CommandPacket.Cdb = Cdb;
765 //
766 // Fill Cdb for Read (10) Command
767 //
768 Cdb[0] = EFI_SCSI_OP_READ10;
769 Cdb[2] = (UINT8) (StartLba >> 24);
770 Cdb[3] = (UINT8) (StartLba >> 16);
771 Cdb[4] = (UINT8) (StartLba >> 8);
772 Cdb[5] = (UINT8) (StartLba & 0xff);
773 Cdb[7] = (UINT8) (SectorSize >> 8);
774 Cdb[8] = (UINT8) (SectorSize & 0xff);
775
776 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
777 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
778 CommandPacket.SenseDataLength = *SenseDataLength;
779
780 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
781
782 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
783 *TargetStatus = CommandPacket.TargetStatus;
784 *SenseDataLength = CommandPacket.SenseDataLength;
785 *DataLength = CommandPacket.InTransferLength;
786
787 return Status;
788 }
789
790
791 /**
792 Execute Write(10) SCSI command on a specific SCSI target.
793
794 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
795 If Timeout is zero, then this function waits indefinitely for the command to complete.
796 If Timeout is greater than zero, then the command is executed and will timeout after
797 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
798 the CDB for this SCSI command.
799 If ScsiIo is NULL, then ASSERT().
800 If SenseDataLength is NULL, then ASSERT().
801 If HostAdapterStatus is NULL, then ASSERT().
802 If TargetStatus is NULL, then ASSERT().
803 If DataLength is NULL, then ASSERT().
804
805 @param[in] ScsiIo SCSI IO Protocol to use
806 @param[in] Timeout The length of timeout period.
807 @param[in, out] SenseData A pointer to output sense data.
808 @param[in, out] SenseDataLength The length of output sense data.
809 @param[out] HostAdapterStatus The status of Host Adapter.
810 @param[out] TargetStatus The status of the target.
811 @param[in, out] DataBuffer A pointer to a data buffer.
812 @param[in, out] DataLength The length of data buffer.
813 @param[in] StartLba The start address of LBA.
814 @param[in] SectorSize The sector size.
815
816 @retval EFI_SUCCESS Command is executed successfully.
817 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
818 not be transferred. The actual number of bytes transferred is returned in DataLength.
819 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
820 SCSI Command Packets already queued.
821 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
822 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
823 the SCSI initiator(i.e., SCSI Host Controller)
824 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
825
826 **/
827 EFI_STATUS
828 EFIAPI
829 ScsiWrite10Command (
830 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
831 IN UINT64 Timeout,
832 IN OUT VOID *SenseData, OPTIONAL
833 IN OUT UINT8 *SenseDataLength,
834 OUT UINT8 *HostAdapterStatus,
835 OUT UINT8 *TargetStatus,
836 IN OUT VOID *DataBuffer, OPTIONAL
837 IN OUT UINT32 *DataLength,
838 IN UINT32 StartLba,
839 IN UINT32 SectorSize
840 )
841 {
842 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
843 EFI_STATUS Status;
844 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
845
846 ASSERT (SenseDataLength != NULL);
847 ASSERT (HostAdapterStatus != NULL);
848 ASSERT (TargetStatus != NULL);
849 ASSERT (DataLength != NULL);
850 ASSERT (ScsiIo != NULL);
851
852 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
853 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
854
855 CommandPacket.Timeout = Timeout;
856 CommandPacket.OutDataBuffer = DataBuffer;
857 CommandPacket.SenseData = SenseData;
858 CommandPacket.OutTransferLength= *DataLength;
859 CommandPacket.Cdb = Cdb;
860 //
861 // Fill Cdb for Write (10) Command
862 //
863 Cdb[0] = EFI_SCSI_OP_WRITE10;
864 Cdb[2] = (UINT8) (StartLba >> 24);
865 Cdb[3] = (UINT8) (StartLba >> 16);
866 Cdb[4] = (UINT8) (StartLba >> 8);
867 Cdb[5] = (UINT8) StartLba;
868 Cdb[7] = (UINT8) (SectorSize >> 8);
869 Cdb[8] = (UINT8) SectorSize;
870
871 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
872 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
873 CommandPacket.SenseDataLength = *SenseDataLength;
874
875 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
876
877 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
878 *TargetStatus = CommandPacket.TargetStatus;
879 *SenseDataLength = CommandPacket.SenseDataLength;
880 *DataLength = CommandPacket.OutTransferLength;
881
882 return Status;
883 }
884