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