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