2 UEFI SCSI Library implementation
\r
4 Copyright (c) 2006 - 2007, Intel Corporation.<BR>
\r
5 All rights reserved. This program and the accompanying materials
\r
6 are licensed and made available under the terms and conditions of the BSD License
\r
7 which accompanies this distribution. The full text of the license may be found at
\r
8 http://opensource.org/licenses/bsd-license.php
\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
17 #include <Library/DebugLib.h>
\r
18 #include <Library/ScsiLib.h>
\r
19 #include <Library/BaseMemoryLib.h>
\r
21 #include <IndustryStandard/Scsi.h>
\r
25 Function test the ready status of the SCSI unit.
\r
27 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
28 @param[in] Timeout The length of timeout period.
\r
29 @param[in out] SenseData A pointer to the sense data that
\r
30 was generated by the execution of the SCSI Request Packet.
\r
31 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
32 output, the number of bytes written to the SenseData buffer.
\r
33 @param[out] HostAdapterStatus The status of Host Adapter.
\r
34 @param[out] TargetStatus The status of the target.
\r
36 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
37 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
38 but the entire DataBuffer could not be transferred.
\r
39 The actual number of bytes transferred is returned
\r
40 in InTransferLength.
\r
41 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
42 there are too many SCSI Command Packets already
\r
44 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
45 the SCSI Request Packet.
\r
46 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
47 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
48 is not supported by the SCSI initiator(i.e., SCSI
\r
50 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
51 Request Packet to execute.
\r
55 ScsiTestUnitReadyCommand (
\r
56 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
58 IN OUT VOID *SenseData,
\r
59 IN OUT UINT8 *SenseDataLength,
\r
60 OUT UINT8 *HostAdapterStatus,
\r
61 OUT UINT8 *TargetStatus
\r
64 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
67 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
71 ASSERT (SenseDataLength != NULL);
\r
72 ASSERT (HostAdapterStatus != NULL);
\r
73 ASSERT (TargetStatus != NULL);
\r
75 if (ScsiIo == NULL) {
\r
76 return EFI_INVALID_PARAMETER;
\r
79 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
82 CommandPacket.Timeout = Timeout;
\r
83 CommandPacket.InDataBuffer = NULL;
\r
84 CommandPacket.InTransferLength= 0;
\r
85 CommandPacket.OutDataBuffer = NULL;
\r
86 CommandPacket.OutTransferLength= 0;
\r
87 CommandPacket.SenseData = SenseData;
\r
88 CommandPacket.Cdb = Cdb;
\r
90 // Fill Cdb for Test Unit Ready Command
\r
92 Target = &TargetArray[0];
\r
93 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
95 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
\r
96 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
97 CommandPacket.CdbLength = (UINT8) 6;
\r
98 CommandPacket.SenseDataLength = *SenseDataLength;
\r
100 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
102 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
103 *TargetStatus = CommandPacket.TargetStatus;
\r
104 *SenseDataLength = CommandPacket.SenseDataLength;
\r
111 Function to submit SCSI inquiry command.
\r
113 @param[in] ScsiIo SCSI IO Protocol to use
\r
114 @param[in] Timeout The length of timeout period.
\r
115 @param[out] SenseData A pointer to output sense data.
\r
116 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
117 output, the number of bytes written to the SenseData buffer.
\r
118 @param[out] HostAdapterStatus The status of Host Adapter.
\r
119 @param[out] TargetStatus The status of the target.
\r
120 @param[in] InquirydataBuffer A pointer to inquiry data buffer.
\r
121 @param[in,out] InquiryDataLength The length of inquiry data buffer.
\r
122 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
\r
124 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
125 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
126 but the entire DataBuffer could not be transferred.
\r
127 The actual number of bytes transferred is returned
\r
129 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
130 there are too many SCSI Command Packets already
\r
132 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
133 the SCSI Request Packet.
\r
134 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
135 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
136 is not supported by the SCSI initiator(i.e., SCSI
\r
138 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
139 Request Packet to execute.
\r
143 ScsiInquiryCommand (
\r
144 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
146 IN VOID *SenseData,
\r
147 IN OUT UINT8 *SenseDataLength,
\r
148 OUT UINT8 *HostAdapterStatus,
\r
149 OUT UINT8 *TargetStatus,
\r
150 IN VOID *InquiryDataBuffer,
\r
151 IN OUT UINT32 *InquiryDataLength,
\r
152 IN BOOLEAN EnableVitalProductData
\r
155 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
158 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
162 ASSERT (SenseDataLength != NULL);
\r
163 ASSERT (HostAdapterStatus != NULL);
\r
164 ASSERT (TargetStatus != NULL);
\r
165 ASSERT (InquiryDataLength != NULL);
\r
167 if (ScsiIo == NULL) {
\r
168 return EFI_INVALID_PARAMETER;
\r
171 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
174 CommandPacket.Timeout = Timeout;
\r
175 CommandPacket.InDataBuffer = InquiryDataBuffer;
\r
176 CommandPacket.InTransferLength= *InquiryDataLength;
\r
177 CommandPacket.SenseData = SenseData;
\r
178 CommandPacket.SenseDataLength = *SenseDataLength;
\r
179 CommandPacket.Cdb = Cdb;
\r
181 Target = &TargetArray[0];
\r
182 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
184 Cdb[0] = EFI_SCSI_OP_INQUIRY;
\r
185 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
186 if (EnableVitalProductData) {
\r
190 if (*InquiryDataLength > 0xff) {
\r
191 *InquiryDataLength = 0xff;
\r
194 Cdb[4] = (UINT8) (*InquiryDataLength);
\r
195 CommandPacket.CdbLength = (UINT8) 6;
\r
196 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
198 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
200 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
201 *TargetStatus = CommandPacket.TargetStatus;
\r
202 *SenseDataLength = CommandPacket.SenseDataLength;
\r
203 *InquiryDataLength = CommandPacket.InTransferLength;
\r
210 Function to submit SCSI mode sense 10 command.
\r
212 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
213 @param[in] Timeout The length of timeout period.
\r
214 @param[out] SenseData A pointer to output sense data.
\r
215 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
216 output, the number of bytes written to the SenseData buffer.
\r
217 @param[out] HostAdapterStatus The status of Host Adapter.
\r
218 @param[out] TargetStatus The status of the target.
\r
219 @param[in] DataBuffer A pointer to input data buffer.
\r
220 @param[in,out] DataLength The length of input data buffer.
\r
221 @param[in] DBDField The DBD Field (Optional).
\r
222 @param[in] PageControl Page Control.
\r
223 @param[in] PageCode Page code.
\r
225 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
226 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
227 but the entire DataBuffer could not be transferred.
\r
228 The actual number of bytes transferred is returned
\r
230 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
231 there are too many SCSI Command Packets already
\r
233 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
234 the SCSI Request Packet.
\r
235 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
236 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
237 is not supported by the SCSI initiator(i.e., SCSI
\r
239 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
240 Request Packet to execute.
\r
244 ScsiModeSense10Command (
\r
245 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
247 IN VOID *SenseData,
\r
248 IN OUT UINT8 *SenseDataLength,
\r
249 OUT UINT8 *HostAdapterStatus,
\r
250 OUT UINT8 *TargetStatus,
\r
251 IN VOID *DataBuffer,
\r
252 IN OUT UINT32 *DataLength,
\r
253 IN UINT8 DBDField, OPTIONAL
\r
254 IN UINT8 PageControl,
\r
258 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
261 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
265 ASSERT (SenseDataLength != NULL);
\r
266 ASSERT (HostAdapterStatus != NULL);
\r
267 ASSERT (TargetStatus != NULL);
\r
268 ASSERT (DataLength != NULL);
\r
270 if (ScsiIo == NULL) {
\r
271 return EFI_INVALID_PARAMETER;
\r
274 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
277 CommandPacket.Timeout = Timeout;
\r
278 CommandPacket.InDataBuffer = DataBuffer;
\r
279 CommandPacket.SenseData = SenseData;
\r
280 CommandPacket.InTransferLength= *DataLength;
\r
281 CommandPacket.Cdb = Cdb;
\r
283 // Fill Cdb for Mode Sense (10) Command
\r
285 Target = &TargetArray[0];
\r
286 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
288 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
\r
289 Cdb[1] = (UINT8) ((Lun & 0xe0) + ((DBDField << 3) & 0x08));
\r
290 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));
\r
291 Cdb[7] = (UINT8) (*DataLength >> 8);
\r
292 Cdb[8] = (UINT8) (*DataLength);
\r
294 CommandPacket.CdbLength = 10;
\r
295 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
296 CommandPacket.SenseDataLength = *SenseDataLength;
\r
298 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
300 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
301 *TargetStatus = CommandPacket.TargetStatus;
\r
302 *SenseDataLength = CommandPacket.SenseDataLength;
\r
303 *DataLength = CommandPacket.InTransferLength;
\r
310 Function to submit SCSI request sense command.
\r
312 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
313 @param[in] Timeout The length of timeout period.
\r
314 @param[in] SenseData A pointer to output sense data.
\r
315 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
316 output, the number of bytes written to the SenseData buffer.
\r
317 @param[out] HostAdapterStatus The status of Host Adapter.
\r
318 @param[out] TargetStatus The status of the target.
\r
320 @retval EFI_SUCCESS Valid data returned
\r
321 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
322 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
323 but the entire DataBuffer could not be transferred.
\r
324 The actual number of bytes transferred is returned
\r
326 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
327 there are too many SCSI Command Packets already
\r
329 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
330 the SCSI Request Packet.
\r
331 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
332 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
333 is not supported by the SCSI initiator(i.e., SCSI
\r
335 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
336 Request Packet to execute.
\r
340 ScsiRequestSenseCommand (
\r
341 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
343 IN VOID *SenseData,
\r
344 IN OUT UINT8 *SenseDataLength,
\r
345 OUT UINT8 *HostAdapterStatus,
\r
346 OUT UINT8 *TargetStatus
\r
349 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
352 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
356 ASSERT (SenseDataLength != NULL);
\r
357 ASSERT (HostAdapterStatus != NULL);
\r
358 ASSERT (TargetStatus != NULL);
\r
360 if (ScsiIo == NULL) {
\r
361 return EFI_INVALID_PARAMETER;
\r
364 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
367 CommandPacket.Timeout = Timeout;
\r
368 CommandPacket.InDataBuffer = SenseData;
\r
369 CommandPacket.SenseData = NULL;
\r
370 CommandPacket.InTransferLength= *SenseDataLength;
\r
371 CommandPacket.Cdb = Cdb;
\r
373 // Fill Cdb for Request Sense Command
\r
375 Target = &TargetArray[0];
\r
376 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
378 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
\r
379 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
380 Cdb[4] = (UINT8) (*SenseDataLength);
\r
382 CommandPacket.CdbLength = (UINT8) 6;
\r
383 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
384 CommandPacket.SenseDataLength = 0;
\r
386 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
388 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
389 *TargetStatus = CommandPacket.TargetStatus;
\r
390 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
\r
397 Function to submit read capacity command.
\r
399 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
400 @param[in] Timeout The length of timeout period.
\r
401 @param[out] SenseData A pointer to output sense data.
\r
402 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
403 output, the number of bytes written to the SenseData buffer.
\r
404 @param[out] HostAdapterStatus The status of Host Adapter.
\r
405 @param[out] TargetStatus The status of the target.
\r
406 @param[out] DataBuffer A pointer to a data buffer.
\r
407 @param[in,out] DataLength The length of data buffer.
\r
408 @param[in] PMI Partial medium indicator.
\r
410 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
411 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
412 but the entire DataBuffer could not be transferred.
\r
413 The actual number of bytes transferred is returned
\r
415 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
416 there are too many SCSI Command Packets already
\r
418 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
419 the SCSI Request Packet.
\r
420 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
421 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
422 is not supported by the SCSI initiator(i.e., SCSI
\r
424 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
425 Request Packet to execute.
\r
429 ScsiReadCapacityCommand (
\r
430 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
432 IN VOID *SenseData,
\r
433 IN OUT UINT8 *SenseDataLength,
\r
434 OUT UINT8 *HostAdapterStatus,
\r
435 OUT UINT8 *TargetStatus,
\r
436 OUT VOID *DataBuffer,
\r
437 IN OUT UINT32 *DataLength,
\r
441 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
444 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
448 ASSERT (SenseDataLength != NULL);
\r
449 ASSERT (HostAdapterStatus != NULL);
\r
450 ASSERT (TargetStatus != NULL);
\r
451 ASSERT (DataLength != NULL);
\r
453 if (ScsiIo == NULL) {
\r
454 return EFI_INVALID_PARAMETER;
\r
457 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
460 CommandPacket.Timeout = Timeout;
\r
461 CommandPacket.InDataBuffer = DataBuffer;
\r
462 CommandPacket.SenseData = SenseData;
\r
463 CommandPacket.InTransferLength= *DataLength;
\r
464 CommandPacket.Cdb = Cdb;
\r
466 // Fill Cdb for Read Capacity Command
\r
468 Target = &TargetArray[0];
\r
469 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
471 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
\r
472 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
475 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
\r
477 ZeroMem ((Cdb + 2), 4);
\r
482 CommandPacket.CdbLength = 10;
\r
483 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
484 CommandPacket.SenseDataLength = *SenseDataLength;
\r
486 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
488 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
489 *TargetStatus = CommandPacket.TargetStatus;
\r
490 *SenseDataLength = CommandPacket.SenseDataLength;
\r
491 *DataLength = CommandPacket.InTransferLength;
\r
498 Function to submit read 10 command.
\r
500 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
501 @param[in] Timeout The length of timeout period.
\r
502 @param[out] SenseData A pointer to output sense data.
\r
503 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
504 output, the number of bytes written to the SenseData buffer.
\r
505 @param[out] HostAdapterStatus The status of Host Adapter.
\r
506 @param[out] TargetStatus The status of the target.
\r
507 @param[out] DataBuffer Read 10 command data.
\r
508 @param[in,out] DataLength The length of data buffer.
\r
509 @param[in] StartLba The start address of LBA.
\r
510 @param[in] SectorSize The sector size.
\r
512 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
513 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
514 but the entire DataBuffer could not be transferred.
\r
515 The actual number of bytes transferred is returned
\r
517 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
518 there are too many SCSI Command Packets already
\r
520 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
521 the SCSI Request Packet.
\r
522 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
523 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
524 is not supported by the SCSI initiator(i.e., SCSI
\r
526 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
527 Request Packet to execute.
\r
531 ScsiRead10Command (
\r
532 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
534 IN VOID *SenseData,
\r
535 IN OUT UINT8 *SenseDataLength,
\r
536 OUT UINT8 *HostAdapterStatus,
\r
537 OUT UINT8 *TargetStatus,
\r
538 OUT VOID *DataBuffer,
\r
539 IN OUT UINT32 *DataLength,
\r
540 IN UINT32 StartLba,
\r
541 IN UINT32 SectorSize
\r
544 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
547 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
551 ASSERT (SenseDataLength != NULL);
\r
552 ASSERT (HostAdapterStatus != NULL);
\r
553 ASSERT (TargetStatus != NULL);
\r
554 ASSERT (DataLength != NULL);
\r
556 if (ScsiIo == NULL) {
\r
557 return EFI_INVALID_PARAMETER;
\r
560 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
563 CommandPacket.Timeout = Timeout;
\r
564 CommandPacket.InDataBuffer = DataBuffer;
\r
565 CommandPacket.SenseData = SenseData;
\r
566 CommandPacket.InTransferLength= *DataLength;
\r
567 CommandPacket.Cdb = Cdb;
\r
569 // Fill Cdb for Read (10) Command
\r
571 Target = &TargetArray[0];
\r
572 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
574 Cdb[0] = EFI_SCSI_OP_READ10;
\r
575 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
576 Cdb[2] = (UINT8) (StartLba >> 24);
\r
577 Cdb[3] = (UINT8) (StartLba >> 16);
\r
578 Cdb[4] = (UINT8) (StartLba >> 8);
\r
579 Cdb[5] = (UINT8) (StartLba & 0xff);
\r
580 Cdb[7] = (UINT8) (SectorSize >> 8);
\r
581 Cdb[8] = (UINT8) (SectorSize & 0xff);
\r
583 CommandPacket.CdbLength = 10;
\r
584 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
585 CommandPacket.SenseDataLength = *SenseDataLength;
\r
587 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
589 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
590 *TargetStatus = CommandPacket.TargetStatus;
\r
591 *SenseDataLength = CommandPacket.SenseDataLength;
\r
592 *DataLength = CommandPacket.InTransferLength;
\r
599 Function to submit SCSI write 10 command.
\r
601 @param[in] ScsiIo SCSI IO Protocol to use
\r
602 @param[in] Timeout The length of timeout period.
\r
603 @param[out] SenseData A pointer to output sense data.
\r
604 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
605 output, the number of bytes written to the SenseData buffer.
\r
606 @param[out] HostAdapterStatus The status of Host Adapter.
\r
607 @param[out] TargetStatus The status of the target.
\r
608 @param[out] DataBuffer A pointer to a data buffer.
\r
609 @param[in,out] DataLength The length of data buffer.
\r
610 @param[in] StartLba The start address of LBA.
\r
611 @param[in] SectorSize The sector size.
\r
613 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
614 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
615 but the entire DataBuffer could not be transferred.
\r
616 The actual number of bytes transferred is returned
\r
617 in InTransferLength.
\r
618 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
619 there are too many SCSI Command Packets already
\r
621 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
622 the SCSI Request Packet.
\r
623 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
624 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
625 is not supported by the SCSI initiator(i.e., SCSI
\r
627 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
628 Request Packet to execute.
\r
632 ScsiWrite10Command (
\r
633 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
635 IN VOID *SenseData,
\r
636 IN OUT UINT8 *SenseDataLength,
\r
637 OUT UINT8 *HostAdapterStatus,
\r
638 OUT UINT8 *TargetStatus,
\r
639 OUT VOID *DataBuffer,
\r
640 IN OUT UINT32 *DataLength,
\r
641 IN UINT32 StartLba,
\r
642 IN UINT32 SectorSize
\r
645 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
648 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
652 ASSERT (SenseDataLength != NULL);
\r
653 ASSERT (HostAdapterStatus != NULL);
\r
654 ASSERT (TargetStatus != NULL);
\r
655 ASSERT (DataLength != NULL);
\r
657 if (ScsiIo == NULL) {
\r
658 return EFI_INVALID_PARAMETER;
\r
661 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
664 CommandPacket.Timeout = Timeout;
\r
665 CommandPacket.OutDataBuffer = DataBuffer;
\r
666 CommandPacket.SenseData = SenseData;
\r
667 CommandPacket.OutTransferLength= *DataLength;
\r
668 CommandPacket.Cdb = Cdb;
\r
670 // Fill Cdb for Write (10) Command
\r
672 Target = &TargetArray[0];
\r
673 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
675 Cdb[0] = EFI_SCSI_OP_WRITE10;
\r
676 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
677 Cdb[2] = (UINT8) (StartLba >> 24);
\r
678 Cdb[3] = (UINT8) (StartLba >> 16);
\r
679 Cdb[4] = (UINT8) (StartLba >> 8);
\r
680 Cdb[5] = (UINT8) StartLba;
\r
681 Cdb[7] = (UINT8) (SectorSize >> 8);
\r
682 Cdb[8] = (UINT8) SectorSize;
\r
684 CommandPacket.CdbLength = 10;
\r
685 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
\r
686 CommandPacket.SenseDataLength = *SenseDataLength;
\r
688 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
690 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
691 *TargetStatus = CommandPacket.TargetStatus;
\r
692 *SenseDataLength = CommandPacket.SenseDataLength;
\r
693 *DataLength = CommandPacket.OutTransferLength;
\r