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