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/ScsiLib.h>
\r
18 #include <Library/BaseMemoryLib.h>
\r
20 #include <IndustryStandard/Scsi.h>
\r
24 Function test the ready status of the SCSI unit.
\r
26 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
27 @param[in] Timeout The length of timeout period.
\r
28 @param[in out] SenseData A pointer to the sense data that
\r
29 was generated by the execution of the SCSI Request Packet.
\r
30 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
31 output, the number of bytes written to the SenseData buffer.
\r
32 @param[out] HostAdapterStatus The status of Host Adapter.
\r
33 @param[out] TargetStatus The status of the target.
\r
35 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
36 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
37 but the entire DataBuffer could not be transferred.
\r
38 The actual number of bytes transferred is returned
\r
39 in InTransferLength.
\r
40 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
41 there are too many SCSI Command Packets already
\r
43 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
44 the SCSI Request Packet.
\r
45 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
46 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
47 is not supported by the SCSI initiator(i.e., SCSI
\r
49 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
50 Request Packet to execute.
\r
54 ScsiTestUnitReadyCommand (
\r
55 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
57 IN OUT VOID *SenseData,
\r
58 IN OUT UINT8 *SenseDataLength,
\r
59 OUT UINT8 *HostAdapterStatus,
\r
60 OUT UINT8 *TargetStatus
\r
63 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
66 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
70 ASSERT (SenseDataLength != NULL);
\r
71 ASSERT (HostAdapterStatus != NULL);
\r
72 ASSERT (TargetStatus != NULL);
\r
74 if (ScsiIo == NULL) {
\r
75 return EFI_INVALID_PARAMETER;
\r
78 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
81 CommandPacket.Timeout = Timeout;
\r
82 CommandPacket.InDataBuffer = NULL;
\r
83 CommandPacket.InTransferLength= 0;
\r
84 CommandPacket.OutDataBuffer = NULL;
\r
85 CommandPacket.OutTransferLength= 0;
\r
86 CommandPacket.SenseData = SenseData;
\r
87 CommandPacket.Cdb = Cdb;
\r
89 // Fill Cdb for Test Unit Ready Command
\r
91 Target = &TargetArray[0];
\r
92 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
94 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
\r
95 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
96 CommandPacket.CdbLength = (UINT8) 6;
\r
97 CommandPacket.SenseDataLength = *SenseDataLength;
\r
99 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
101 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
102 *TargetStatus = CommandPacket.TargetStatus;
\r
103 *SenseDataLength = CommandPacket.SenseDataLength;
\r
110 Function to submit SCSI inquiry command.
\r
112 @param[in] ScsiIo SCSI IO Protocol to use
\r
113 @param[in] Timeout The length of timeout period.
\r
114 @param[out] SenseData A pointer to output sense data.
\r
115 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
116 output, the number of bytes written to the SenseData buffer.
\r
117 @param[out] HostAdapterStatus The status of Host Adapter.
\r
118 @param[out] TargetStatus The status of the target.
\r
119 @param[in] InquirydataBuffer A pointer to inquiry data buffer.
\r
120 @param[in,out] InquiryDataLength The length of inquiry data buffer.
\r
121 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
\r
123 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
124 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
125 but the entire DataBuffer could not be transferred.
\r
126 The actual number of bytes transferred is returned
\r
128 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
129 there are too many SCSI Command Packets already
\r
131 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
132 the SCSI Request Packet.
\r
133 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
134 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
135 is not supported by the SCSI initiator(i.e., SCSI
\r
137 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
138 Request Packet to execute.
\r
142 ScsiInquiryCommand (
\r
143 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
145 IN VOID *SenseData,
\r
146 IN OUT UINT8 *SenseDataLength,
\r
147 OUT UINT8 *HostAdapterStatus,
\r
148 OUT UINT8 *TargetStatus,
\r
149 IN VOID *InquiryDataBuffer,
\r
150 IN OUT UINT32 *InquiryDataLength,
\r
151 IN BOOLEAN EnableVitalProductData
\r
154 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
157 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
161 ASSERT (SenseDataLength != NULL);
\r
162 ASSERT (HostAdapterStatus != NULL);
\r
163 ASSERT (TargetStatus != NULL);
\r
164 ASSERT (InquiryDataLength != NULL);
\r
166 if (ScsiIo == NULL) {
\r
167 return EFI_INVALID_PARAMETER;
\r
170 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
173 CommandPacket.Timeout = Timeout;
\r
174 CommandPacket.InDataBuffer = InquiryDataBuffer;
\r
175 CommandPacket.InTransferLength= *InquiryDataLength;
\r
176 CommandPacket.SenseData = SenseData;
\r
177 CommandPacket.SenseDataLength = *SenseDataLength;
\r
178 CommandPacket.Cdb = Cdb;
\r
180 Target = &TargetArray[0];
\r
181 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
183 Cdb[0] = EFI_SCSI_OP_INQUIRY;
\r
184 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
185 if (EnableVitalProductData) {
\r
189 if (*InquiryDataLength > 0xff) {
\r
190 *InquiryDataLength = 0xff;
\r
193 Cdb[4] = (UINT8) (*InquiryDataLength);
\r
194 CommandPacket.CdbLength = (UINT8) 6;
\r
195 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
197 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
199 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
200 *TargetStatus = CommandPacket.TargetStatus;
\r
201 *SenseDataLength = CommandPacket.SenseDataLength;
\r
202 *InquiryDataLength = CommandPacket.InTransferLength;
\r
209 Function to submit SCSI mode sense 10 command.
\r
211 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
212 @param[in] Timeout The length of timeout period.
\r
213 @param[out] SenseData A pointer to output sense data.
\r
214 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
215 output, the number of bytes written to the SenseData buffer.
\r
216 @param[out] HostAdapterStatus The status of Host Adapter.
\r
217 @param[out] TargetStatus The status of the target.
\r
218 @param[in] DataBuffer A pointer to input data buffer.
\r
219 @param[in,out] DataLength The length of input data buffer.
\r
220 @param[in] DBDField The DBD Field (Optional).
\r
221 @param[in] PageControl Page Control.
\r
222 @param[in] PageCode Page code.
\r
224 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
225 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
226 but the entire DataBuffer could not be transferred.
\r
227 The actual number of bytes transferred is returned
\r
229 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
230 there are too many SCSI Command Packets already
\r
232 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
233 the SCSI Request Packet.
\r
234 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
235 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
236 is not supported by the SCSI initiator(i.e., SCSI
\r
238 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
239 Request Packet to execute.
\r
243 ScsiModeSense10Command (
\r
244 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
246 IN VOID *SenseData,
\r
247 IN OUT UINT8 *SenseDataLength,
\r
248 OUT UINT8 *HostAdapterStatus,
\r
249 OUT UINT8 *TargetStatus,
\r
250 IN VOID *DataBuffer,
\r
251 IN OUT UINT32 *DataLength,
\r
252 IN UINT8 DBDField, OPTIONAL
\r
253 IN UINT8 PageControl,
\r
257 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
260 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
264 ASSERT (SenseDataLength != NULL);
\r
265 ASSERT (HostAdapterStatus != NULL);
\r
266 ASSERT (TargetStatus != NULL);
\r
267 ASSERT (DataLength != NULL);
\r
269 if (ScsiIo == NULL) {
\r
270 return EFI_INVALID_PARAMETER;
\r
273 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
276 CommandPacket.Timeout = Timeout;
\r
277 CommandPacket.InDataBuffer = DataBuffer;
\r
278 CommandPacket.SenseData = SenseData;
\r
279 CommandPacket.InTransferLength= *DataLength;
\r
280 CommandPacket.Cdb = Cdb;
\r
282 // Fill Cdb for Mode Sense (10) Command
\r
284 Target = &TargetArray[0];
\r
285 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
287 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
\r
288 Cdb[1] = (UINT8) ((Lun & 0xe0) + ((DBDField << 3) & 0x08));
\r
289 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));
\r
290 Cdb[7] = (UINT8) (*DataLength >> 8);
\r
291 Cdb[8] = (UINT8) (*DataLength);
\r
293 CommandPacket.CdbLength = 10;
\r
294 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
295 CommandPacket.SenseDataLength = *SenseDataLength;
\r
297 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
299 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
300 *TargetStatus = CommandPacket.TargetStatus;
\r
301 *SenseDataLength = CommandPacket.SenseDataLength;
\r
302 *DataLength = CommandPacket.InTransferLength;
\r
309 Function to submit SCSI request sense command.
\r
311 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
312 @param[in] Timeout The length of timeout period.
\r
313 @param[in] SenseData A pointer to output sense data.
\r
314 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
315 output, the number of bytes written to the SenseData buffer.
\r
316 @param[out] HostAdapterStatus The status of Host Adapter.
\r
317 @param[out] TargetStatus The status of the target.
\r
319 @retval EFI_SUCCESS Valid data returned
\r
320 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
321 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
322 but the entire DataBuffer could not be transferred.
\r
323 The actual number of bytes transferred is returned
\r
325 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
326 there are too many SCSI Command Packets already
\r
328 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
329 the SCSI Request Packet.
\r
330 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
331 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
332 is not supported by the SCSI initiator(i.e., SCSI
\r
334 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
335 Request Packet to execute.
\r
339 ScsiRequestSenseCommand (
\r
340 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
342 IN VOID *SenseData,
\r
343 IN OUT UINT8 *SenseDataLength,
\r
344 OUT UINT8 *HostAdapterStatus,
\r
345 OUT UINT8 *TargetStatus
\r
348 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
351 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
355 ASSERT (SenseDataLength != NULL);
\r
356 ASSERT (HostAdapterStatus != NULL);
\r
357 ASSERT (TargetStatus != NULL);
\r
359 if (ScsiIo == NULL) {
\r
360 return EFI_INVALID_PARAMETER;
\r
363 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
366 CommandPacket.Timeout = Timeout;
\r
367 CommandPacket.InDataBuffer = SenseData;
\r
368 CommandPacket.SenseData = NULL;
\r
369 CommandPacket.InTransferLength= *SenseDataLength;
\r
370 CommandPacket.Cdb = Cdb;
\r
372 // Fill Cdb for Request Sense Command
\r
374 Target = &TargetArray[0];
\r
375 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
377 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
\r
378 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
379 Cdb[4] = (UINT8) (*SenseDataLength);
\r
381 CommandPacket.CdbLength = (UINT8) 6;
\r
382 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
383 CommandPacket.SenseDataLength = 0;
\r
385 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
387 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
388 *TargetStatus = CommandPacket.TargetStatus;
\r
389 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
\r
396 Function to submit read capacity command.
\r
398 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
399 @param[in] Timeout The length of timeout period.
\r
400 @param[out] SenseData A pointer to output sense data.
\r
401 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
402 output, the number of bytes written to the SenseData buffer.
\r
403 @param[out] HostAdapterStatus The status of Host Adapter.
\r
404 @param[out] TargetStatus The status of the target.
\r
405 @param[out] DataBuffer A pointer to a data buffer.
\r
406 @param[in,out] DataLength The length of data buffer.
\r
407 @param[in] PMI Partial medium indicator.
\r
409 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
410 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
411 but the entire DataBuffer could not be transferred.
\r
412 The actual number of bytes transferred is returned
\r
414 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
415 there are too many SCSI Command Packets already
\r
417 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
418 the SCSI Request Packet.
\r
419 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
420 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
421 is not supported by the SCSI initiator(i.e., SCSI
\r
423 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
424 Request Packet to execute.
\r
428 ScsiReadCapacityCommand (
\r
429 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
431 IN VOID *SenseData,
\r
432 IN OUT UINT8 *SenseDataLength,
\r
433 OUT UINT8 *HostAdapterStatus,
\r
434 OUT UINT8 *TargetStatus,
\r
435 OUT VOID *DataBuffer,
\r
436 IN OUT UINT32 *DataLength,
\r
440 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
443 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
447 ASSERT (SenseDataLength != NULL);
\r
448 ASSERT (HostAdapterStatus != NULL);
\r
449 ASSERT (TargetStatus != NULL);
\r
450 ASSERT (DataLength != NULL);
\r
452 if (ScsiIo == NULL) {
\r
453 return EFI_INVALID_PARAMETER;
\r
456 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
459 CommandPacket.Timeout = Timeout;
\r
460 CommandPacket.InDataBuffer = DataBuffer;
\r
461 CommandPacket.SenseData = SenseData;
\r
462 CommandPacket.InTransferLength= *DataLength;
\r
463 CommandPacket.Cdb = Cdb;
\r
465 // Fill Cdb for Read Capacity Command
\r
467 Target = &TargetArray[0];
\r
468 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
470 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
\r
471 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
474 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
\r
476 ZeroMem ((Cdb + 2), 4);
\r
481 CommandPacket.CdbLength = 10;
\r
482 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
483 CommandPacket.SenseDataLength = *SenseDataLength;
\r
485 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
487 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
488 *TargetStatus = CommandPacket.TargetStatus;
\r
489 *SenseDataLength = CommandPacket.SenseDataLength;
\r
490 *DataLength = CommandPacket.InTransferLength;
\r
497 Function to submit read 10 command.
\r
499 @param[in] ScsiIo A pointer to SCSI IO protocol.
\r
500 @param[in] Timeout The length of timeout period.
\r
501 @param[out] SenseData A pointer to output sense data.
\r
502 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
503 output, the number of bytes written to the SenseData buffer.
\r
504 @param[out] HostAdapterStatus The status of Host Adapter.
\r
505 @param[out] TargetStatus The status of the target.
\r
506 @param[out] DataBuffer Read 10 command data.
\r
507 @param[in,out] DataLength The length of data buffer.
\r
508 @param[in] StartLba The start address of LBA.
\r
509 @param[in] SectorSize The sector size.
\r
511 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
512 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
513 but the entire DataBuffer could not be transferred.
\r
514 The actual number of bytes transferred is returned
\r
516 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
517 there are too many SCSI Command Packets already
\r
519 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
520 the SCSI Request Packet.
\r
521 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
522 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
523 is not supported by the SCSI initiator(i.e., SCSI
\r
525 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
526 Request Packet to execute.
\r
530 ScsiRead10Command (
\r
531 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
533 IN VOID *SenseData,
\r
534 IN OUT UINT8 *SenseDataLength,
\r
535 OUT UINT8 *HostAdapterStatus,
\r
536 OUT UINT8 *TargetStatus,
\r
537 OUT VOID *DataBuffer,
\r
538 IN OUT UINT32 *DataLength,
\r
539 IN UINT32 StartLba,
\r
540 IN UINT32 SectorSize
\r
543 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
546 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
550 ASSERT (SenseDataLength != NULL);
\r
551 ASSERT (HostAdapterStatus != NULL);
\r
552 ASSERT (TargetStatus != NULL);
\r
553 ASSERT (DataLength != NULL);
\r
555 if (ScsiIo == NULL) {
\r
556 return EFI_INVALID_PARAMETER;
\r
559 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
562 CommandPacket.Timeout = Timeout;
\r
563 CommandPacket.InDataBuffer = DataBuffer;
\r
564 CommandPacket.SenseData = SenseData;
\r
565 CommandPacket.InTransferLength= *DataLength;
\r
566 CommandPacket.Cdb = Cdb;
\r
568 // Fill Cdb for Read (10) Command
\r
570 Target = &TargetArray[0];
\r
571 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
573 Cdb[0] = EFI_SCSI_OP_READ10;
\r
574 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
575 Cdb[2] = (UINT8) (StartLba >> 24);
\r
576 Cdb[3] = (UINT8) (StartLba >> 16);
\r
577 Cdb[4] = (UINT8) (StartLba >> 8);
\r
578 Cdb[5] = (UINT8) (StartLba & 0xff);
\r
579 Cdb[7] = (UINT8) (SectorSize >> 8);
\r
580 Cdb[8] = (UINT8) (SectorSize & 0xff);
\r
582 CommandPacket.CdbLength = 10;
\r
583 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
\r
584 CommandPacket.SenseDataLength = *SenseDataLength;
\r
586 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
588 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
589 *TargetStatus = CommandPacket.TargetStatus;
\r
590 *SenseDataLength = CommandPacket.SenseDataLength;
\r
591 *DataLength = CommandPacket.InTransferLength;
\r
598 Function to submit SCSI write 10 command.
\r
600 @param[in] ScsiIo SCSI IO Protocol to use
\r
601 @param[in] Timeout The length of timeout period.
\r
602 @param[out] SenseData A pointer to output sense data.
\r
603 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
\r
604 output, the number of bytes written to the SenseData buffer.
\r
605 @param[out] HostAdapterStatus The status of Host Adapter.
\r
606 @param[out] TargetStatus The status of the target.
\r
607 @param[out] DataBuffer A pointer to a data buffer.
\r
608 @param[in,out] DataLength The length of data buffer.
\r
609 @param[in] StartLba The start address of LBA.
\r
610 @param[in] SectorSize The sector size.
\r
612 @retval EFI_SUCCESS The status of the unit is tested successfully.
\r
613 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
\r
614 but the entire DataBuffer could not be transferred.
\r
615 The actual number of bytes transferred is returned
\r
616 in InTransferLength.
\r
617 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
\r
618 there are too many SCSI Command Packets already
\r
620 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
\r
621 the SCSI Request Packet.
\r
622 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
\r
623 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
\r
624 is not supported by the SCSI initiator(i.e., SCSI
\r
626 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
\r
627 Request Packet to execute.
\r
631 ScsiWrite10Command (
\r
632 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
\r
634 IN VOID *SenseData,
\r
635 IN OUT UINT8 *SenseDataLength,
\r
636 OUT UINT8 *HostAdapterStatus,
\r
637 OUT UINT8 *TargetStatus,
\r
638 OUT VOID *DataBuffer,
\r
639 IN OUT UINT32 *DataLength,
\r
640 IN UINT32 StartLba,
\r
641 IN UINT32 SectorSize
\r
644 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
\r
647 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
\r
651 ASSERT (SenseDataLength != NULL);
\r
652 ASSERT (HostAdapterStatus != NULL);
\r
653 ASSERT (TargetStatus != NULL);
\r
654 ASSERT (DataLength != NULL);
\r
656 if (ScsiIo == NULL) {
\r
657 return EFI_INVALID_PARAMETER;
\r
660 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
\r
663 CommandPacket.Timeout = Timeout;
\r
664 CommandPacket.OutDataBuffer = DataBuffer;
\r
665 CommandPacket.SenseData = SenseData;
\r
666 CommandPacket.OutTransferLength= *DataLength;
\r
667 CommandPacket.Cdb = Cdb;
\r
669 // Fill Cdb for Write (10) Command
\r
671 Target = &TargetArray[0];
\r
672 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
\r
674 Cdb[0] = EFI_SCSI_OP_WRITE10;
\r
675 Cdb[1] = (UINT8) (Lun & 0xe0);
\r
676 Cdb[2] = (UINT8) (StartLba >> 24);
\r
677 Cdb[3] = (UINT8) (StartLba >> 16);
\r
678 Cdb[4] = (UINT8) (StartLba >> 8);
\r
679 Cdb[5] = (UINT8) StartLba;
\r
680 Cdb[7] = (UINT8) (SectorSize >> 8);
\r
681 Cdb[8] = (UINT8) SectorSize;
\r
683 CommandPacket.CdbLength = 10;
\r
684 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
\r
685 CommandPacket.SenseDataLength = *SenseDataLength;
\r
687 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
\r
689 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
\r
690 *TargetStatus = CommandPacket.TargetStatus;
\r
691 *SenseDataLength = CommandPacket.SenseDataLength;
\r
692 *DataLength = CommandPacket.OutTransferLength;
\r