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