]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
65f169f4d882e06c3d1d19c37f48d57e2d79e692
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
1 /** @file
2 UEFI SCSI Library implementation
3
4 Copyright (c) 2006 - 2007, 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/ScsiLib.h>
19 #include <Library/BaseMemoryLib.h>
20
21 #include <IndustryStandard/Scsi.h>
22
23 //
24 // bit5..7 are for Logical unit number
25 // 11100000b (0xe0)
26 //
27 #define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0
28
29 //
30 // Scsi Command Length six or ten
31 //
32 #define EFI_SCSI_OP_LENGTH_SIX 0x6
33 #define EFI_SCSI_OP_LENGTH_TEN 0xa
34
35 /**
36 Function test the ready status of the SCSI unit.
37
38 Submit SCSI test unit ready command with SCSI request packet specified by this scsi command, TimeOut
39 and SenseData, then get the status of the target Scsi unit.
40
41 If SenseDataLength is NULL, then ASSERT().
42
43 If HostAdapterStatus is NULL, then ASSERT().
44
45 If TargetStatus is NULL, then ASSERT().
46
47 @param[in] ScsiIo A pointer to SCSI IO protocol.
48 @param[in] Timeout The length of timeout period.
49 @param[in] SenseData A pointer to output sense data.
50 @param[out] SenseDataLength The length of output sense data.
51 @param[out] HostAdapterStatus The status of Host Adapter.
52 @param[out] TargetStatus The status of the target.
53
54 @retval EFI_SUCCESS The status of the unit is tested successfully.
55 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
56 but the entire DataBuffer could not be transferred.
57 The actual number of bytes transferred is returned
58 in InTransferLength.
59 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
60 there are too many SCSI Command Packets already
61 queued.
62 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
63 the SCSI Request Packet.
64 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
65 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
66 is not supported by the SCSI initiator(i.e., SCSI
67 Host Controller).
68 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
69 Request Packet to execute.
70
71 **/
72 EFI_STATUS
73 EFIAPI
74 ScsiTestUnitReadyCommand (
75 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
76 IN UINT64 Timeout,
77 IN VOID *SenseData,
78 OUT UINT8 *SenseDataLength,
79 OUT UINT8 *HostAdapterStatus,
80 OUT UINT8 *TargetStatus
81 )
82 {
83 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
84 UINT64 Lun;
85 UINT8 *Target;
86 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
87 EFI_STATUS Status;
88 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
89
90 ASSERT (SenseDataLength != NULL);
91 ASSERT (HostAdapterStatus != NULL);
92 ASSERT (TargetStatus != NULL);
93
94 if (ScsiIo == NULL) {
95 return EFI_INVALID_PARAMETER;
96 }
97
98 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
99 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
100
101 CommandPacket.Timeout = Timeout;
102 CommandPacket.InDataBuffer = NULL;
103 CommandPacket.InTransferLength= 0;
104 CommandPacket.OutDataBuffer = NULL;
105 CommandPacket.OutTransferLength= 0;
106 CommandPacket.SenseData = SenseData;
107 CommandPacket.Cdb = Cdb;
108 //
109 // Fill Cdb for Test Unit Ready Command
110 //
111 Target = &TargetArray[0];
112 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
113
114 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
115 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
116 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
117 CommandPacket.SenseDataLength = *SenseDataLength;
118
119 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
120
121 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
122 *TargetStatus = CommandPacket.TargetStatus;
123 *SenseDataLength = CommandPacket.SenseDataLength;
124
125 return Status;
126 }
127
128
129 /**
130 Function to submit SCSI inquiry command.
131
132 Submit SCSI inquiry command with the SCSI request packet specified by this SCSI command and input
133 parameters, then return the status of Scsi unit execution.
134
135 If SenseDataLength is NULL, then ASSERT().
136
137 If HostAdapterStatus is NULL, then ASSERT().
138
139 If TargetStatus is NULL, then ASSERT().
140
141 If InquiryDataLength is NULL, then ASSERT().
142
143 @param[in] ScsiIo SCSI IO Protocol to use
144 @param[in] Timeout The length of timeout period.
145 @param[in] SenseData A pointer to output sense data.
146 @param[in out] SenseDataLength The length of output sense data.
147 @param[out] HostAdapterStatus The status of Host Adapter.
148 @param[out] TargetStatus The status of the target.
149 @param[in out] InquirydataBuffer A pointer to inquiry data buffer.
150 @param[in out] InquiryDataLength The length of inquiry data buffer.
151 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
152
153 @retval EFI_SUCCESS Command is executed successfully.
154 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
155 but the entire DataBuffer could not be transferred.
156 The actual number of bytes transferred is returned
157 in TransferLength.
158 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
159 there are too many SCSI Command Packets already
160 queued.
161 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
162 the SCSI Request Packet.
163 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
164 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
165 is not supported by the SCSI initiator(i.e., SCSI
166 Host Controller).
167 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
168 Request Packet to execute.
169
170 **/
171 EFI_STATUS
172 EFIAPI
173 ScsiInquiryCommand (
174 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
175 IN UINT64 Timeout,
176 IN VOID *SenseData,
177 IN OUT UINT8 *SenseDataLength,
178 OUT UINT8 *HostAdapterStatus,
179 OUT UINT8 *TargetStatus,
180 IN OUT VOID *InquiryDataBuffer,
181 IN OUT UINT32 *InquiryDataLength,
182 IN BOOLEAN EnableVitalProductData
183 )
184 {
185 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
186 UINT64 Lun;
187 UINT8 *Target;
188 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
189 EFI_STATUS Status;
190 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
191
192 ASSERT (SenseDataLength != NULL);
193 ASSERT (HostAdapterStatus != NULL);
194 ASSERT (TargetStatus != NULL);
195 ASSERT (InquiryDataLength != NULL);
196
197 if (ScsiIo == NULL) {
198 return EFI_INVALID_PARAMETER;
199 }
200
201 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
202 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
203
204 CommandPacket.Timeout = Timeout;
205 CommandPacket.InDataBuffer = InquiryDataBuffer;
206 CommandPacket.InTransferLength= *InquiryDataLength;
207 CommandPacket.SenseData = SenseData;
208 CommandPacket.SenseDataLength = *SenseDataLength;
209 CommandPacket.Cdb = Cdb;
210
211 Target = &TargetArray[0];
212 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
213
214 Cdb[0] = EFI_SCSI_OP_INQUIRY;
215 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
216 if (EnableVitalProductData) {
217 Cdb[1] |= 0x01;
218 }
219
220 if (*InquiryDataLength > 0xff) {
221 *InquiryDataLength = 0xff;
222 }
223
224 Cdb[4] = (UINT8) (*InquiryDataLength);
225 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
226 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
227
228 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
229
230 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
231 *TargetStatus = CommandPacket.TargetStatus;
232 *SenseDataLength = CommandPacket.SenseDataLength;
233 *InquiryDataLength = CommandPacket.InTransferLength;
234
235 return Status;
236 }
237
238
239 /**
240 Function to submit SCSI mode sense 10 command.
241
242 Submit SCSI Mode Sense (10) command with the SCSI request packet specified by this SCSI command and
243 the input parameters, then return the status of Scsi unit execution.
244
245 If SenseDataLength is NULL, then ASSERT().
246
247 If HostAdapterStatus is NULL, then ASSERT().
248
249 If TargetStatus is NULL, then ASSERT().
250
251 If DataLength is NULL, then ASSERT().
252
253 @param[in] ScsiIo A pointer to SCSI IO protocol.
254 @param[in] Timeout The length of timeout period.
255 @param[in] SenseData A pointer to output sense data.
256 @param[in out] SenseDataLength The length of output sense data.
257 @param[out] HostAdapterStatus The status of Host Adapter.
258 @param[out] TargetStatus The status of the target.
259 @param[in] DataBuffer A pointer to input data buffer.
260 @param[in out] DataLength The length of input data buffer.
261 @param[in] DBDField The DBD Field (Optional).
262 @param[in] PageControl Page Control.
263 @param[in] PageCode Page code.
264
265 @retval EFI_SUCCESS The status of the unit is tested successfully.
266 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
267 but the entire DataBuffer could not be transferred.
268 The actual number of bytes transferred is returned
269 in TransferLength.
270 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
271 there are too many SCSI Command Packets already
272 queued.
273 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
274 the SCSI Request Packet.
275 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
276 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
277 is not supported by the SCSI initiator(i.e., SCSI
278 Host Controller).
279 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
280 Request Packet to execute.
281
282 **/
283 EFI_STATUS
284 EFIAPI
285 ScsiModeSense10Command (
286 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
287 IN UINT64 Timeout,
288 IN VOID *SenseData,
289 IN OUT UINT8 *SenseDataLength,
290 OUT UINT8 *HostAdapterStatus,
291 OUT UINT8 *TargetStatus,
292 IN VOID *DataBuffer,
293 IN OUT UINT32 *DataLength,
294 IN UINT8 DBDField, OPTIONAL
295 IN UINT8 PageControl,
296 IN UINT8 PageCode
297 )
298 {
299 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
300 UINT64 Lun;
301 UINT8 *Target;
302 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
303 EFI_STATUS Status;
304 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
305
306 ASSERT (SenseDataLength != NULL);
307 ASSERT (HostAdapterStatus != NULL);
308 ASSERT (TargetStatus != NULL);
309 ASSERT (DataLength != NULL);
310
311 if (ScsiIo == NULL) {
312 return EFI_INVALID_PARAMETER;
313 }
314
315 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
316 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
317
318 CommandPacket.Timeout = Timeout;
319 CommandPacket.InDataBuffer = DataBuffer;
320 CommandPacket.SenseData = SenseData;
321 CommandPacket.InTransferLength= *DataLength;
322 CommandPacket.Cdb = Cdb;
323 //
324 // Fill Cdb for Mode Sense (10) Command
325 //
326 Target = &TargetArray[0];
327 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
328
329 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
330 //
331 // DBDField is in Cdb[1] bit3 of (bit7..0)
332 //
333 Cdb[1] = (UINT8) ((Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));
334 //
335 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
336 //
337 Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));
338 Cdb[7] = (UINT8) (*DataLength >> 8);
339 Cdb[8] = (UINT8) (*DataLength);
340
341 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
342 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
343 CommandPacket.SenseDataLength = *SenseDataLength;
344
345 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
346
347 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
348 *TargetStatus = CommandPacket.TargetStatus;
349 *SenseDataLength = CommandPacket.SenseDataLength;
350 *DataLength = CommandPacket.InTransferLength;
351
352 return Status;
353 }
354
355
356 /**
357 Function to submit SCSI request sense command.
358
359 Submit SCSI request sense command with the SCSI requested packet specified by this
360 SCSI command, TimeOut and SenseData, and then return the status of scsi unit execution.
361
362 If SenseDataLength is NULL, then ASSERT().
363
364 If HostAdapterStatus is NULL, then ASSERT().
365
366 If TargetStatus is NULL, then ASSERT().
367
368 @param[in] ScsiIo A pointer to SCSI IO protocol.
369 @param[in] Timeout The length of timeout period.
370 @param[in] SenseData A pointer to output sense data.
371 @param[in out] SenseDataLength The length of output sense data.
372 @param[out] HostAdapterStatus The status of Host Adapter.
373 @param[out] TargetStatus The status of the target.
374
375 @retval EFI_SUCCESS Command is executed successfully.
376 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
377 too many SCSI Command Packets already queued.
378 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
379 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
380 the SCSI initiator(i.e., SCSI Host Controller)
381 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
382 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
383
384 **/
385 EFI_STATUS
386 EFIAPI
387 ScsiRequestSenseCommand (
388 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
389 IN UINT64 Timeout,
390 IN VOID *SenseData,
391 IN OUT UINT8 *SenseDataLength,
392 OUT UINT8 *HostAdapterStatus,
393 OUT UINT8 *TargetStatus
394 )
395 {
396 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
397 UINT64 Lun;
398 UINT8 *Target;
399 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
400 EFI_STATUS Status;
401 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
402
403 ASSERT (SenseDataLength != NULL);
404 ASSERT (HostAdapterStatus != NULL);
405 ASSERT (TargetStatus != NULL);
406
407 if (ScsiIo == NULL) {
408 return EFI_INVALID_PARAMETER;
409 }
410
411 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
412 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
413
414 CommandPacket.Timeout = Timeout;
415 CommandPacket.InDataBuffer = SenseData;
416 CommandPacket.SenseData = NULL;
417 CommandPacket.InTransferLength= *SenseDataLength;
418 CommandPacket.Cdb = Cdb;
419 //
420 // Fill Cdb for Request Sense Command
421 //
422 Target = &TargetArray[0];
423 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
424
425 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
426 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
427 Cdb[4] = (UINT8) (*SenseDataLength);
428
429 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
430 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
431 CommandPacket.SenseDataLength = 0;
432
433 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
434
435 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
436 *TargetStatus = CommandPacket.TargetStatus;
437 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
438
439 return Status;
440 }
441
442
443 /**
444 Function to submit read capacity command.
445
446 Submit SCSI read capacity command with the SCSI request packet specified by this SCSI
447 command and the input parameters, and then return the status of Scsi unit execution.
448
449 If SenseDataLength is NULL, then ASSERT().
450
451 If HostAdapterStatus is NULL, then ASSERT().
452
453 If TargetStatus is NULL, then ASSERT().
454
455 If DataLength is NULL, then ASSERT().
456
457 @param[in] ScsiIo A pointer to SCSI IO protocol.
458 @param[in] Timeout The length of timeout period.
459 @param[in] SenseData A pointer to output sense data.
460 @param[in out] SenseDataLength The length of output sense data.
461 @param[out] HostAdapterStatus The status of Host Adapter.
462 @param[out] TargetStatus The status of the target.
463 @param[out] DataBuffer A pointer to a data buffer.
464 @param[in out] DataLength The length of data buffer.
465 @param[in] PMI Partial medium indicator.
466
467 @retval EFI_SUCCESS Command is executed successfully.
468 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
469 not be transferred. The actual number of bytes transferred is returned in DataLength.
470 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
471 SCSI Command Packets already queued.
472 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
473 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
474 the SCSI initiator(i.e., SCSI Host Controller)
475 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
476 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
477
478 **/
479 EFI_STATUS
480 EFIAPI
481 ScsiReadCapacityCommand (
482 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
483 IN UINT64 Timeout,
484 IN VOID *SenseData,
485 IN OUT UINT8 *SenseDataLength,
486 OUT UINT8 *HostAdapterStatus,
487 OUT UINT8 *TargetStatus,
488 OUT VOID *DataBuffer,
489 IN OUT UINT32 *DataLength,
490 IN BOOLEAN PMI
491 )
492 {
493 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
494 UINT64 Lun;
495 UINT8 *Target;
496 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
497 EFI_STATUS Status;
498 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
499
500 ASSERT (SenseDataLength != NULL);
501 ASSERT (HostAdapterStatus != NULL);
502 ASSERT (TargetStatus != NULL);
503 ASSERT (DataLength != NULL);
504
505 if (ScsiIo == NULL) {
506 return EFI_INVALID_PARAMETER;
507 }
508
509 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
510 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
511
512 CommandPacket.Timeout = Timeout;
513 CommandPacket.InDataBuffer = DataBuffer;
514 CommandPacket.SenseData = SenseData;
515 CommandPacket.InTransferLength= *DataLength;
516 CommandPacket.Cdb = Cdb;
517 //
518 // Fill Cdb for Read Capacity Command
519 //
520 Target = &TargetArray[0];
521 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
522
523 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
524 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
525 if (!PMI) {
526 //
527 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
528 //
529 ZeroMem ((Cdb + 2), 4);
530 } else {
531 Cdb[8] |= 0x01;
532 }
533
534 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
535 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
536 CommandPacket.SenseDataLength = *SenseDataLength;
537
538 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
539
540 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
541 *TargetStatus = CommandPacket.TargetStatus;
542 *SenseDataLength = CommandPacket.SenseDataLength;
543 *DataLength = CommandPacket.InTransferLength;
544
545 return Status;
546 }
547
548
549 /**
550 Function to submit read 10 command.
551
552 Submit SCSI read (10) command with the SCSI request packet specified by this SCSI command
553 and the input parameters, and then return the status of Scsi unit execution.
554
555 If SenseDataLength is NULL, then ASSERT().
556
557 If HostAdapterStatus is NULL, then ASSERT().
558
559 If TargetStatus is NULL, then ASSERT().
560
561 If DataLength is NULL, then ASSERT().
562
563 @param[in] ScsiIo A pointer to SCSI IO protocol.
564 @param[in] Timeout The length of timeout period.
565 @param[in] SenseData A pointer to output sense data.
566 @param[in out] SenseDataLength The length of output sense data.
567 @param[out] HostAdapterStatus The status of Host Adapter.
568 @param[out] TargetStatus The status of the target.
569 @param[out] DataBuffer Read 10 command data.
570 @param[in out] DataLength The length of data buffer.
571 @param[in] StartLba The start address of LBA.
572 @param[in] SectorSize The sector size.
573
574 @retval EFI_SUCCESS Command is executed successfully.
575 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
576 not be transferred. The actual number of bytes transferred is returned in DataLength.
577 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
578 SCSI Command Packets already queued.
579 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
580 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
581 the SCSI initiator(i.e., SCSI Host Controller)
582 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
583 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
584
585 **/
586 EFI_STATUS
587 EFIAPI
588 ScsiRead10Command (
589 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
590 IN UINT64 Timeout,
591 IN VOID *SenseData,
592 IN OUT UINT8 *SenseDataLength,
593 OUT UINT8 *HostAdapterStatus,
594 OUT UINT8 *TargetStatus,
595 OUT VOID *DataBuffer,
596 IN OUT UINT32 *DataLength,
597 IN UINT32 StartLba,
598 IN UINT32 SectorSize
599 )
600 {
601 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
602 UINT64 Lun;
603 UINT8 *Target;
604 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
605 EFI_STATUS Status;
606 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
607
608 ASSERT (SenseDataLength != NULL);
609 ASSERT (HostAdapterStatus != NULL);
610 ASSERT (TargetStatus != NULL);
611 ASSERT (DataLength != NULL);
612
613 if (ScsiIo == NULL) {
614 return EFI_INVALID_PARAMETER;
615 }
616
617 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
618 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
619
620 CommandPacket.Timeout = Timeout;
621 CommandPacket.InDataBuffer = DataBuffer;
622 CommandPacket.SenseData = SenseData;
623 CommandPacket.InTransferLength= *DataLength;
624 CommandPacket.Cdb = Cdb;
625 //
626 // Fill Cdb for Read (10) Command
627 //
628 Target = &TargetArray[0];
629 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
630
631 Cdb[0] = EFI_SCSI_OP_READ10;
632 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
633 Cdb[2] = (UINT8) (StartLba >> 24);
634 Cdb[3] = (UINT8) (StartLba >> 16);
635 Cdb[4] = (UINT8) (StartLba >> 8);
636 Cdb[5] = (UINT8) (StartLba & 0xff);
637 Cdb[7] = (UINT8) (SectorSize >> 8);
638 Cdb[8] = (UINT8) (SectorSize & 0xff);
639
640 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
641 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
642 CommandPacket.SenseDataLength = *SenseDataLength;
643
644 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
645
646 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
647 *TargetStatus = CommandPacket.TargetStatus;
648 *SenseDataLength = CommandPacket.SenseDataLength;
649 *DataLength = CommandPacket.InTransferLength;
650
651 return Status;
652 }
653
654
655 /**
656 Function to submit SCSI write 10 command.
657
658 Submit SCSI write (10) command with the SCSI request packet specified by this SCSI command and the
659 input parameters, and then return the status of Scsi unit execution.
660
661 If SenseDataLength is NULL, then ASSERT().
662
663 If HostAdapterStatus is NULL, then ASSERT().
664
665 If TargetStatus is NULL, then ASSERT().
666
667 If DataLength is NULL, then ASSERT().
668
669 @param[in] ScsiIo SCSI IO Protocol to use
670 @param[in] Timeout The length of timeout period.
671 @param[in] SenseData A pointer to output sense data.
672 @param[in out] SenseDataLength The length of output sense data.
673 @param[out] HostAdapterStatus The status of Host Adapter.
674 @param[out] TargetStatus The status of the target.
675 @param[out] DataBuffer A pointer to a data buffer.
676 @param[in out] DataLength The length of data buffer.
677 @param[in] StartLba The start address of LBA.
678 @param[in] SectorSize The sector size.
679
680 @retval EFI_SUCCESS Command is executed successfully.
681 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
682 not be transferred. The actual number of bytes transferred is returned in DataLength.
683 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
684 SCSI Command Packets already queued.
685 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
686 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
687 the SCSI initiator(i.e., SCSI Host Controller)
688 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
689 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
690
691 **/
692 EFI_STATUS
693 EFIAPI
694 ScsiWrite10Command (
695 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
696 IN UINT64 Timeout,
697 IN VOID *SenseData,
698 IN OUT UINT8 *SenseDataLength,
699 OUT UINT8 *HostAdapterStatus,
700 OUT UINT8 *TargetStatus,
701 OUT VOID *DataBuffer,
702 IN OUT UINT32 *DataLength,
703 IN UINT32 StartLba,
704 IN UINT32 SectorSize
705 )
706 {
707 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
708 UINT64 Lun;
709 UINT8 *Target;
710 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
711 EFI_STATUS Status;
712 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
713
714 ASSERT (SenseDataLength != NULL);
715 ASSERT (HostAdapterStatus != NULL);
716 ASSERT (TargetStatus != NULL);
717 ASSERT (DataLength != NULL);
718
719 if (ScsiIo == NULL) {
720 return EFI_INVALID_PARAMETER;
721 }
722
723 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
724 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
725
726 CommandPacket.Timeout = Timeout;
727 CommandPacket.OutDataBuffer = DataBuffer;
728 CommandPacket.SenseData = SenseData;
729 CommandPacket.OutTransferLength= *DataLength;
730 CommandPacket.Cdb = Cdb;
731 //
732 // Fill Cdb for Write (10) Command
733 //
734 Target = &TargetArray[0];
735 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
736
737 Cdb[0] = EFI_SCSI_OP_WRITE10;
738 Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);
739 Cdb[2] = (UINT8) (StartLba >> 24);
740 Cdb[3] = (UINT8) (StartLba >> 16);
741 Cdb[4] = (UINT8) (StartLba >> 8);
742 Cdb[5] = (UINT8) StartLba;
743 Cdb[7] = (UINT8) (SectorSize >> 8);
744 Cdb[8] = (UINT8) SectorSize;
745
746 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
747 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
748 CommandPacket.SenseDataLength = *SenseDataLength;
749
750 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
751
752 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
753 *TargetStatus = CommandPacket.TargetStatus;
754 *SenseDataLength = CommandPacket.SenseDataLength;
755 *DataLength = CommandPacket.OutTransferLength;
756
757 return Status;
758 }
759