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