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