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