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