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