]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
Fix the unaligned issue of PCI read/write buffer.
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
... / ...
CommitLineData
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
4 Copyright (c) 2006 - 2008, 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 <Uefi.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiScsiLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20 \r
21#include <IndustryStandard/Scsi.h>\r
22 \r
23 \r
24 //\r
25 // Max bytes needed to represent ID of a SCSI device\r
26 //\r
27#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
28 \r
29 //\r
30 // bit5..7 are for Logical unit number\r
31 // 11100000b (0xe0)\r
32 //\r
33#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
34 \r
35 //\r
36 // Scsi Command Length six or ten\r
37 //\r
38#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
39#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
40\r
41\r
42\r
43/**\r
44 Execute Test Unit Ready SCSI command on a specific SCSI target.\r
45\r
46 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
47 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
48 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
49 If ScsiIo is NULL, then ASSERT().\r
50 If SenseDataLength is NULL, then ASSERT().\r
51 If HostAdapterStatus is NULL, then ASSERT().\r
52 If TargetStatus is NULL, then ASSERT().\r
53\r
54\r
55 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
56 for the specific SCSI target.\r
57 @param[in] Timeout The timeout in 100 ns units to use for the execution\r
58 of this SCSI Request Packet. A Timeout value of\r
59 zero means that this function will wait indefinitely\r
60 for the SCSI Request Packet to execute. If Timeout\r
61 is greater than zero, then this function will return\r
62 EFI_TIMEOUT if the time required to execute the SCSI\r
63 Request Packet is greater than Timeout.\r
64 @param[in, out] SenseData A pointer to sense data that was generated by\r
65 the execution of the SCSI Request Packet. This\r
66 buffer must be allocated by the caller.\r
67 If SenseDataLength is 0, then this parameter is\r
68 optional and may be NULL.\r
69 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
70 the SenseData buffer. On output, a pointer to\r
71 the number of bytes written to the SenseData buffer. \r
72 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
73 the SCSI bus containing the SCSI target specified by\r
74 ScsiIo when the SCSI Request Packet was executed.\r
75 See the EFI SCSI I/O Protocol in the UEFI Specification\r
76 for details on the possible return values.\r
77 @param[out] TargetStatus The status returned by the SCSI target specified\r
78 by ScsiIo when the SCSI Request Packet was executed\r
79 on the SCSI Host Controller. See the EFI SCSI I/O\r
80 Protocol in the UEFI Specification for details on\r
81 the possible return values. \r
82\r
83 @retval EFI_SUCCESS The command was executed successfully.\r
84 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
85 and SenseData in that order for additional status\r
86 information.\r
87 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
88 there are too many SCSI Command Packets already\r
89 queued. The SCSI Request Packet was not sent, so\r
90 no additional status information is available.\r
91 The caller may retry again later.\r
92 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
93 SCSI Request Packet. See HostAdapterStatus,\r
94 TargetStatus, SenseDataLength, and SenseData in that\r
95 order for additional status information.\r
96 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
97 is not supported by the SCSI initiator(i.e., SCSI\r
98 Host Controller). The SCSI Request Packet was not\r
99 sent, so no additional status information is available.\r
100 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
101 Packet to execute. See HostAdapterStatus, TargetStatus,\r
102 SenseDataLength, and SenseData in that order for\r
103 additional status information.\r
104\r
105**/\r
106EFI_STATUS\r
107EFIAPI\r
108ScsiTestUnitReadyCommand (\r
109 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
110 IN UINT64 Timeout,\r
111 IN OUT VOID *SenseData, OPTIONAL\r
112 IN OUT UINT8 *SenseDataLength,\r
113 OUT UINT8 *HostAdapterStatus,\r
114 OUT UINT8 *TargetStatus\r
115 )\r
116{\r
117 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
118 EFI_STATUS Status;\r
119 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
120\r
121 ASSERT (SenseDataLength != NULL);\r
122 ASSERT (HostAdapterStatus != NULL);\r
123 ASSERT (TargetStatus != NULL);\r
124 ASSERT (ScsiIo != NULL);\r
125\r
126 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
127 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
128\r
129 CommandPacket.Timeout = Timeout;\r
130 CommandPacket.InDataBuffer = NULL;\r
131 CommandPacket.InTransferLength= 0;\r
132 CommandPacket.OutDataBuffer = NULL;\r
133 CommandPacket.OutTransferLength= 0;\r
134 CommandPacket.SenseData = SenseData;\r
135 CommandPacket.Cdb = Cdb;\r
136 //\r
137 // Fill Cdb for Test Unit Ready Command\r
138 //\r
139 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
140 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
141 CommandPacket.SenseDataLength = *SenseDataLength;\r
142\r
143 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
144\r
145 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
146 *TargetStatus = CommandPacket.TargetStatus;\r
147 *SenseDataLength = CommandPacket.SenseDataLength;\r
148\r
149 return Status;\r
150}\r
151\r
152\r
153/**\r
154 Execute Inquiry SCSI command on a specific SCSI target.\r
155\r
156 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
157 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
158 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
159 If ScsiIo is NULL, then ASSERT().\r
160 If SenseDataLength is NULL, then ASSERT().\r
161 If HostAdapterStatus is NULL, then ASSERT().\r
162 If TargetStatus is NULL, then ASSERT().\r
163 If InquiryDataLength is NULL, then ASSERT().\r
164\r
165 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
166 for the specific SCSI target.\r
167 @param[in] Timeout The timeout in 100 ns units to use for the\r
168 execution of this SCSI Request Packet. A Timeout\r
169 value of zero means that this function will wait\r
170 indefinitely for the SCSI Request Packet to execute.\r
171 If Timeout is greater than zero, then this function\r
172 will return EFI_TIMEOUT if the time required to\r
173 execute the SCSI Request Packet is greater than Timeout.\r
174 @param[in, out] SenseData A pointer to sense data that was generated\r
175 by the execution of the SCSI Request Packet.\r
176 This buffer must be allocated by the caller.\r
177 If SenseDataLength is 0, then this parameter\r
178 is optional and may be NULL.\r
179 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
180 On output, the number of bytes written to the SenseData buffer. \r
181 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
182 produces the SCSI bus containing the SCSI\r
183 target specified by ScsiIo when the SCSI\r
184 Request Packet was executed. See the EFI\r
185 SCSI I/O Protocol in the UEFI Specification\r
186 for details on the possible return values.\r
187 @param[out] TargetStatus The status returned by the SCSI target specified\r
188 by ScsiIo when the SCSI Request Packet was\r
189 executed on the SCSI Host Controller.\r
190 See the EFI SCSI I/O Protocol in the UEFI\r
191 Specification for details on the possible\r
192 return values. \r
193 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
194 by the execution of the SCSI Request Packet.\r
195 This buffer must be allocated by the caller.\r
196 If InquiryDataLength is 0, then this parameter\r
197 is optional and may be NULL. \r
198 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
199 of the InquiryDataBuffer buffer.\r
200 On output, a pointer to the number of bytes\r
201 written to the InquiryDataBuffer buffer.\r
202 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
203 data is returned in InquiryDataBuffer.\r
204 If FALSE, then the standard inquiry data is\r
205 returned in InquiryDataBuffer. \r
206\r
207 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,\r
208 TargetStatus, SenseDataLength, and SenseData in that order\r
209 for additional status information.\r
210 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
211 InquiryDataBuffer could not be transferred. The actual\r
212 number of bytes transferred is returned in InquiryDataLength.\r
213 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
214 are too many SCSI Command Packets already queued.\r
215 The SCSI Request Packet was not sent, so no additional\r
216 status information is available. The caller may retry again later.\r
217 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
218 Request Packet. See HostAdapterStatus, TargetStatus,\r
219 SenseDataLength, and SenseData in that order for additional\r
220 status information.\r
221 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
222 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
223 The SCSI Request Packet was not sent, so no additional\r
224 status information is available.\r
225 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
226 Packet to execute. See HostAdapterStatus, TargetStatus,\r
227 SenseDataLength, and SenseData in that order for\r
228 additional status information.\r
229\r
230**/\r
231EFI_STATUS\r
232EFIAPI\r
233ScsiInquiryCommand (\r
234 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
235 IN UINT64 Timeout,\r
236 IN OUT VOID *SenseData, OPTIONAL\r
237 IN OUT UINT8 *SenseDataLength,\r
238 OUT UINT8 *HostAdapterStatus,\r
239 OUT UINT8 *TargetStatus,\r
240 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
241 IN OUT UINT32 *InquiryDataLength,\r
242 IN BOOLEAN EnableVitalProductData\r
243 )\r
244{\r
245 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
246 EFI_STATUS Status;\r
247 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
248\r
249 ASSERT (SenseDataLength != NULL);\r
250 ASSERT (HostAdapterStatus != NULL);\r
251 ASSERT (TargetStatus != NULL);\r
252 ASSERT (InquiryDataLength != NULL);\r
253 ASSERT (ScsiIo != NULL);\r
254\r
255 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
256 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
257\r
258 CommandPacket.Timeout = Timeout;\r
259 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
260 CommandPacket.InTransferLength= *InquiryDataLength;\r
261 CommandPacket.SenseData = SenseData;\r
262 CommandPacket.SenseDataLength = *SenseDataLength;\r
263 CommandPacket.Cdb = Cdb;\r
264\r
265 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
266 if (EnableVitalProductData) {\r
267 Cdb[1] |= 0x01;\r
268 }\r
269\r
270 if (*InquiryDataLength > 0xff) {\r
271 *InquiryDataLength = 0xff;\r
272 }\r
273\r
274 Cdb[4] = (UINT8) (*InquiryDataLength);\r
275 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
276 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
277\r
278 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
279\r
280 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
281 *TargetStatus = CommandPacket.TargetStatus;\r
282 *SenseDataLength = CommandPacket.SenseDataLength;\r
283 *InquiryDataLength = CommandPacket.InTransferLength;\r
284\r
285 return Status;\r
286}\r
287\r
288\r
289/**\r
290 Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
291\r
292 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
293 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
294 If Timeout is greater than zero, then the command is executed and will timeout\r
295 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
296 are used to construct the CDB for this SCSI command.\r
297 If ScsiIo is NULL, then ASSERT().\r
298 If SenseDataLength is NULL, then ASSERT().\r
299 If HostAdapterStatus is NULL, then ASSERT().\r
300 If TargetStatus is NULL, then ASSERT().\r
301 If DataLength is NULL, then ASSERT().\r
302\r
303\r
304 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
305 for the specific SCSI target.\r
306 @param[in] Timeout The timeout in 100 ns units to use for the\r
307 execution of this SCSI Request Packet. A Timeout\r
308 value of zero means that this function will wait\r
309 indefinitely for the SCSI Request Packet to execute.\r
310 If Timeout is greater than zero, then this function\r
311 will return EFI_TIMEOUT if the time required to\r
312 execute the SCSI Request Packet is greater than Timeout.\r
313 @param[in, out] SenseData A pointer to sense data that was generated\r
314 by the execution of the SCSI Request Packet.\r
315 This buffer must be allocated by the caller.\r
316 If SenseDataLength is 0, then this parameter\r
317 is optional and may be NULL.\r
318 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
319 On output, the number of bytes written to the SenseData buffer. \r
320 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
321 produces the SCSI bus containing the SCSI target\r
322 specified by ScsiIo when the SCSI Request Packet\r
323 was executed. See the EFI SCSI I/O Protocol in the\r
324 UEFI Specification for details on the possible\r
325 return values.\r
326 @param[out] TargetStatus The status returned by the SCSI target specified\r
327 by ScsiIo when the SCSI Request Packet was executed\r
328 on the SCSI Host Controller. See the EFI SCSI\r
329 I/O Protocol in the UEFI Specification for details\r
330 on the possible return values.\r
331 @param[in, out] DataBuffer A pointer to data that was generated by the\r
332 execution of the SCSI Request Packet. This\r
333 buffer must be allocated by the caller. If\r
334 DataLength is 0, then this parameter is optional\r
335 and may be NULL. \r
336 @param[in, out] DataLength On input, a pointer to the length in bytes of\r
337 the DataBuffer buffer. On output, a pointer\r
338 to the number of bytes written to the DataBuffer\r
339 buffer. \r
340 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
341 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. \r
342 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. \r
343\r
344 @retval EFI_SUCCESS The command was executed successfully.\r
345 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
346 and SenseData in that order for additional status information.\r
347 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
348 entire DataBuffer could not be transferred.\r
349 The actual number of bytes transferred is returned\r
350 in DataLength.\r
351 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
352 there are too many SCSI Command Packets already queued.\r
353 The SCSI Request Packet was not sent, so no additional\r
354 status information is available. The caller may retry\r
355 again later.\r
356 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
357 SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
358 SenseDataLength, and SenseData in that order for\r
359 additional status information.\r
360 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
361 is not supported by the SCSI initiator(i.e., SCSI\r
362 Host Controller). The SCSI Request Packet was not\r
363 sent, so no additional status information is available.\r
364 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
365 Request Packet to execute. See HostAdapterStatus,\r
366 TargetStatus, SenseDataLength, and SenseData in that\r
367 order for additional status information.\r
368\r
369**/\r
370EFI_STATUS\r
371EFIAPI\r
372ScsiModeSense10Command (\r
373 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
374 IN UINT64 Timeout,\r
375 IN OUT VOID *SenseData, OPTIONAL\r
376 IN OUT UINT8 *SenseDataLength,\r
377 OUT UINT8 *HostAdapterStatus,\r
378 OUT UINT8 *TargetStatus,\r
379 IN OUT VOID *DataBuffer, OPTIONAL\r
380 IN OUT UINT32 *DataLength,\r
381 IN UINT8 DBDField, OPTIONAL\r
382 IN UINT8 PageControl,\r
383 IN UINT8 PageCode\r
384 )\r
385{\r
386 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
387 EFI_STATUS Status;\r
388 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
389\r
390 ASSERT (SenseDataLength != NULL);\r
391 ASSERT (HostAdapterStatus != NULL);\r
392 ASSERT (TargetStatus != NULL);\r
393 ASSERT (DataLength != NULL);\r
394 ASSERT (ScsiIo != NULL);\r
395\r
396 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
397 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
398\r
399 CommandPacket.Timeout = Timeout;\r
400 CommandPacket.InDataBuffer = DataBuffer;\r
401 CommandPacket.SenseData = SenseData;\r
402 CommandPacket.InTransferLength= *DataLength;\r
403 CommandPacket.Cdb = Cdb;\r
404 //\r
405 // Fill Cdb for Mode Sense (10) Command\r
406 //\r
407 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
408 //\r
409 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
410 //\r
411 Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);\r
412 //\r
413 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
414 //\r
415 Cdb[2] = (UINT8) (((PageControl & 0x3) << 6) | (PageCode & 0x3f));\r
416 Cdb[7] = (UINT8) (*DataLength >> 8);\r
417 Cdb[8] = (UINT8) (*DataLength);\r
418\r
419 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
420 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
421 CommandPacket.SenseDataLength = *SenseDataLength;\r
422\r
423 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
424\r
425 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
426 *TargetStatus = CommandPacket.TargetStatus;\r
427 *SenseDataLength = CommandPacket.SenseDataLength;\r
428 *DataLength = CommandPacket.InTransferLength;\r
429\r
430 return Status;\r
431}\r
432\r
433\r
434/**\r
435 Execute Request Sense SCSI command on a specific SCSI target.\r
436\r
437 Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
438 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
439 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
440 If ScsiIo is NULL, then ASSERT().\r
441 If SenseDataLength is NULL, then ASSERT().\r
442 If HostAdapterStatus is NULL, then ASSERT().\r
443 If TargetStatus is NULL, then ASSERT().\r
444\r
445 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
446 @param[in] Timeout The length of timeout period.\r
447 @param[in, out] SenseData A pointer to output sense data.\r
448 @param[in, out] SenseDataLength The length of output sense data.\r
449 @param[out] HostAdapterStatus The status of Host Adapter.\r
450 @param[out] TargetStatus The status of the target.\r
451\r
452 @retval EFI_SUCCESS Command is executed successfully.\r
453 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
454 too many SCSI Command Packets already queued.\r
455 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
456 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
457 the SCSI initiator(i.e., SCSI Host Controller)\r
458 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
459\r
460**/\r
461EFI_STATUS\r
462EFIAPI\r
463ScsiRequestSenseCommand (\r
464 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
465 IN UINT64 Timeout,\r
466 IN OUT VOID *SenseData, OPTIONAL\r
467 IN OUT UINT8 *SenseDataLength,\r
468 OUT UINT8 *HostAdapterStatus,\r
469 OUT UINT8 *TargetStatus\r
470 )\r
471{\r
472 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
473 EFI_STATUS Status;\r
474 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
475\r
476 ASSERT (SenseDataLength != NULL);\r
477 ASSERT (HostAdapterStatus != NULL);\r
478 ASSERT (TargetStatus != NULL);\r
479 ASSERT (ScsiIo != NULL);\r
480\r
481 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
482 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
483\r
484 CommandPacket.Timeout = Timeout;\r
485 CommandPacket.InDataBuffer = SenseData;\r
486 CommandPacket.SenseData = NULL;\r
487 CommandPacket.InTransferLength= *SenseDataLength;\r
488 CommandPacket.Cdb = Cdb;\r
489 //\r
490 // Fill Cdb for Request Sense Command\r
491 //\r
492 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
493 Cdb[4] = (UINT8) (*SenseDataLength);\r
494\r
495 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
496 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
497 CommandPacket.SenseDataLength = 0;\r
498\r
499 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
500\r
501 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
502 *TargetStatus = CommandPacket.TargetStatus;\r
503 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
504\r
505 return Status;\r
506}\r
507\r
508\r
509/**\r
510 Execute Read Capacity SCSI command on a specific SCSI target.\r
511\r
512 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
513 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
514 If Timeout is greater than zero, then the command is executed and will timeout after\r
515 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
516 If ScsiIo is NULL, then ASSERT().\r
517 If SenseDataLength is NULL, then ASSERT().\r
518 If HostAdapterStatus is NULL, then ASSERT().\r
519 If TargetStatus is NULL, then ASSERT().\r
520 If DataLength is NULL, then ASSERT().\r
521\r
522 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
523 @param[in] Timeout The length of timeout period.\r
524 @param[in, out] SenseData A pointer to output sense data.\r
525 @param[in, out] SenseDataLength The length of output sense data.\r
526 @param[out] HostAdapterStatus The status of Host Adapter.\r
527 @param[out] TargetStatus The status of the target.\r
528 @param[in, out] DataBuffer A pointer to a data buffer.\r
529 @param[in, out] DataLength The length of data buffer.\r
530 @param[in] Pmi Partial medium indicator.\r
531\r
532 @retval EFI_SUCCESS Command is executed successfully.\r
533 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
534 DataBuffer could not be transferred. The actual\r
535 number of bytes transferred is returned in DataLength.\r
536 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
537 there are too many SCSI Command Packets already queued.\r
538 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
539 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
540 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
541 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
542\r
543**/\r
544EFI_STATUS\r
545EFIAPI\r
546ScsiReadCapacityCommand (\r
547 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
548 IN UINT64 Timeout,\r
549 IN OUT VOID *SenseData, OPTIONAL\r
550 IN OUT UINT8 *SenseDataLength,\r
551 OUT UINT8 *HostAdapterStatus,\r
552 OUT UINT8 *TargetStatus,\r
553 IN OUT VOID *DataBuffer, OPTIONAL\r
554 IN OUT UINT32 *DataLength,\r
555 IN BOOLEAN Pmi\r
556 )\r
557{\r
558 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
559 EFI_STATUS Status;\r
560 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
561\r
562 ASSERT (SenseDataLength != NULL);\r
563 ASSERT (HostAdapterStatus != NULL);\r
564 ASSERT (TargetStatus != NULL);\r
565 ASSERT (DataLength != NULL);\r
566 ASSERT (ScsiIo != NULL);\r
567\r
568 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
569 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
570\r
571 CommandPacket.Timeout = Timeout;\r
572 CommandPacket.InDataBuffer = DataBuffer;\r
573 CommandPacket.SenseData = SenseData;\r
574 CommandPacket.InTransferLength= *DataLength;\r
575 CommandPacket.Cdb = Cdb;\r
576 //\r
577 // Fill Cdb for Read Capacity Command\r
578 //\r
579 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
580 if (!Pmi) {\r
581 //\r
582 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
583 //\r
584 ZeroMem ((Cdb + 2), 4);\r
585 } else {\r
586 Cdb[8] |= 0x01;\r
587 }\r
588\r
589 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
590 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
591 CommandPacket.SenseDataLength = *SenseDataLength;\r
592\r
593 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
594\r
595 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
596 *TargetStatus = CommandPacket.TargetStatus;\r
597 *SenseDataLength = CommandPacket.SenseDataLength;\r
598 *DataLength = CommandPacket.InTransferLength;\r
599\r
600 return Status;\r
601}\r
602\r
603\r
604/**\r
605 Execute Read Capacity SCSI 16 command on a specific SCSI target.\r
606\r
607 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.\r
608 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
609 If Timeout is greater than zero, then the command is executed and will timeout after\r
610 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
611 If ScsiIo is NULL, then ASSERT().\r
612 If SenseDataLength is NULL, then ASSERT().\r
613 If HostAdapterStatus is NULL, then ASSERT().\r
614 If TargetStatus is NULL, then ASSERT().\r
615 If DataLength is NULL, then ASSERT().\r
616\r
617 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
618 @param[in] Timeout The length of timeout period.\r
619 @param[in, out] SenseData A pointer to output sense data.\r
620 @param[in, out] SenseDataLength The length of output sense data.\r
621 @param[out] HostAdapterStatus The status of Host Adapter.\r
622 @param[out] TargetStatus The status of the target.\r
623 @param[in, out] DataBuffer A pointer to a data buffer.\r
624 @param[in, out] DataLength The length of data buffer.\r
625 @param[in] Pmi Partial medium indicator.\r
626\r
627 @retval EFI_SUCCESS Command is executed successfully.\r
628 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
629 DataBuffer could not be transferred. The actual\r
630 number of bytes transferred is returned in DataLength.\r
631 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
632 there are too many SCSI Command Packets already queued.\r
633 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
634 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
635 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
636 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
637\r
638**/\r
639EFI_STATUS\r
640EFIAPI\r
641ScsiReadCapacity16Command (\r
642 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
643 IN UINT64 Timeout,\r
644 IN OUT VOID *SenseData, OPTIONAL\r
645 IN OUT UINT8 *SenseDataLength,\r
646 OUT UINT8 *HostAdapterStatus,\r
647 OUT UINT8 *TargetStatus,\r
648 IN OUT VOID *DataBuffer, OPTIONAL\r
649 IN OUT UINT32 *DataLength,\r
650 IN BOOLEAN Pmi\r
651 )\r
652{\r
653 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
654 EFI_STATUS Status;\r
655 UINT8 Cdb[16];\r
656\r
657 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
658 ZeroMem (Cdb, 16);\r
659\r
660 CommandPacket.Timeout = Timeout;\r
661 CommandPacket.InDataBuffer = DataBuffer;\r
662 CommandPacket.SenseData = SenseData;\r
663 CommandPacket.InTransferLength= *DataLength;\r
664 CommandPacket.Cdb = Cdb;\r
665 //\r
666 // Fill Cdb for Read Capacity Command\r
667 //\r
668 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
669 Cdb[1] = 0x10;\r
670 if (!Pmi) {\r
671 //\r
672 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
673 //\r
674 ZeroMem ((Cdb + 2), 8);\r
675 } else {\r
676 Cdb[14] |= 0x01;\r
677 }\r
678\r
679 Cdb[13] = 0x20;\r
680 CommandPacket.CdbLength = 16;\r
681 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
682 CommandPacket.SenseDataLength = *SenseDataLength;\r
683\r
684 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
685\r
686 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
687 *TargetStatus = CommandPacket.TargetStatus;\r
688 *SenseDataLength = CommandPacket.SenseDataLength;\r
689 *DataLength = CommandPacket.InTransferLength;\r
690\r
691 return Status;\r
692}\r
693\r
694\r
695/**\r
696 Execute Read(10) SCSI command on a specific SCSI target.\r
697\r
698 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
699 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
700 If Timeout is greater than zero, then the command is executed and will timeout\r
701 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
702 construct the CDB for this SCSI command.\r
703 If ScsiIo is NULL, then ASSERT().\r
704 If SenseDataLength is NULL, then ASSERT().\r
705 If HostAdapterStatus is NULL, then ASSERT().\r
706 If TargetStatus is NULL, then ASSERT().\r
707 If DataLength is NULL, then ASSERT().\r
708\r
709\r
710 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
711 @param[in] Timeout The length of timeout period.\r
712 @param[in, out] SenseData A pointer to output sense data.\r
713 @param[in, out] SenseDataLength The length of output sense data.\r
714 @param[out] HostAdapterStatus The status of Host Adapter.\r
715 @param[out] TargetStatus The status of the target.\r
716 @param[in, out] DataBuffer Read 10 command data.\r
717 @param[in, out] DataLength The length of data buffer.\r
718 @param[in] StartLba The start address of LBA.\r
719 @param[in] SectorSize The sector size.\r
720\r
721 @retval EFI_SUCCESS Command is executed successfully.\r
722 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
723 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
724 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
725 SCSI Command Packets already queued.\r
726 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
727 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
728 the SCSI initiator(i.e., SCSI Host Controller)\r
729 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
730\r
731**/\r
732EFI_STATUS\r
733EFIAPI\r
734ScsiRead10Command (\r
735 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
736 IN UINT64 Timeout,\r
737 IN OUT VOID *SenseData, OPTIONAL\r
738 IN OUT UINT8 *SenseDataLength,\r
739 OUT UINT8 *HostAdapterStatus,\r
740 OUT UINT8 *TargetStatus,\r
741 IN OUT VOID *DataBuffer, OPTIONAL\r
742 IN OUT UINT32 *DataLength,\r
743 IN UINT32 StartLba,\r
744 IN UINT32 SectorSize\r
745 )\r
746{\r
747 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
748 EFI_STATUS Status;\r
749 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
750\r
751 ASSERT (SenseDataLength != NULL);\r
752 ASSERT (HostAdapterStatus != NULL);\r
753 ASSERT (TargetStatus != NULL);\r
754 ASSERT (DataLength != NULL);\r
755 ASSERT (ScsiIo != NULL);\r
756\r
757 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
758 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
759\r
760 CommandPacket.Timeout = Timeout;\r
761 CommandPacket.InDataBuffer = DataBuffer;\r
762 CommandPacket.SenseData = SenseData;\r
763 CommandPacket.InTransferLength= *DataLength;\r
764 CommandPacket.Cdb = Cdb;\r
765 //\r
766 // Fill Cdb for Read (10) Command\r
767 //\r
768 Cdb[0] = EFI_SCSI_OP_READ10;\r
769 Cdb[2] = (UINT8) (StartLba >> 24);\r
770 Cdb[3] = (UINT8) (StartLba >> 16);\r
771 Cdb[4] = (UINT8) (StartLba >> 8);\r
772 Cdb[5] = (UINT8) (StartLba & 0xff);\r
773 Cdb[7] = (UINT8) (SectorSize >> 8);\r
774 Cdb[8] = (UINT8) (SectorSize & 0xff);\r
775\r
776 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
777 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
778 CommandPacket.SenseDataLength = *SenseDataLength;\r
779\r
780 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
781\r
782 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
783 *TargetStatus = CommandPacket.TargetStatus;\r
784 *SenseDataLength = CommandPacket.SenseDataLength;\r
785 *DataLength = CommandPacket.InTransferLength;\r
786\r
787 return Status;\r
788}\r
789\r
790\r
791/**\r
792 Execute Write(10) SCSI command on a specific SCSI target.\r
793\r
794 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
795 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
796 If Timeout is greater than zero, then the command is executed and will timeout after\r
797 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
798 the CDB for this SCSI command.\r
799 If ScsiIo is NULL, then ASSERT().\r
800 If SenseDataLength is NULL, then ASSERT().\r
801 If HostAdapterStatus is NULL, then ASSERT().\r
802 If TargetStatus is NULL, then ASSERT().\r
803 If DataLength is NULL, then ASSERT().\r
804\r
805 @param[in] ScsiIo SCSI IO Protocol to use\r
806 @param[in] Timeout The length of timeout period.\r
807 @param[in, out] SenseData A pointer to output sense data.\r
808 @param[in, out] SenseDataLength The length of output sense data.\r
809 @param[out] HostAdapterStatus The status of Host Adapter.\r
810 @param[out] TargetStatus The status of the target.\r
811 @param[in, out] DataBuffer A pointer to a data buffer.\r
812 @param[in, out] DataLength The length of data buffer.\r
813 @param[in] StartLba The start address of LBA.\r
814 @param[in] SectorSize The sector size.\r
815\r
816 @retval EFI_SUCCESS Command is executed successfully.\r
817 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
818 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
819 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
820 SCSI Command Packets already queued.\r
821 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
822 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
823 the SCSI initiator(i.e., SCSI Host Controller)\r
824 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
825\r
826**/\r
827EFI_STATUS\r
828EFIAPI\r
829ScsiWrite10Command (\r
830 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
831 IN UINT64 Timeout,\r
832 IN OUT VOID *SenseData, OPTIONAL\r
833 IN OUT UINT8 *SenseDataLength,\r
834 OUT UINT8 *HostAdapterStatus,\r
835 OUT UINT8 *TargetStatus,\r
836 IN OUT VOID *DataBuffer, OPTIONAL\r
837 IN OUT UINT32 *DataLength,\r
838 IN UINT32 StartLba,\r
839 IN UINT32 SectorSize\r
840 )\r
841{\r
842 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
843 EFI_STATUS Status;\r
844 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
845\r
846 ASSERT (SenseDataLength != NULL);\r
847 ASSERT (HostAdapterStatus != NULL);\r
848 ASSERT (TargetStatus != NULL);\r
849 ASSERT (DataLength != NULL);\r
850 ASSERT (ScsiIo != NULL);\r
851\r
852 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
853 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
854\r
855 CommandPacket.Timeout = Timeout;\r
856 CommandPacket.OutDataBuffer = DataBuffer;\r
857 CommandPacket.SenseData = SenseData;\r
858 CommandPacket.OutTransferLength= *DataLength;\r
859 CommandPacket.Cdb = Cdb;\r
860 //\r
861 // Fill Cdb for Write (10) Command\r
862 //\r
863 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
864 Cdb[2] = (UINT8) (StartLba >> 24);\r
865 Cdb[3] = (UINT8) (StartLba >> 16);\r
866 Cdb[4] = (UINT8) (StartLba >> 8);\r
867 Cdb[5] = (UINT8) StartLba;\r
868 Cdb[7] = (UINT8) (SectorSize >> 8);\r
869 Cdb[8] = (UINT8) SectorSize;\r
870\r
871 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
872 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
873 CommandPacket.SenseDataLength = *SenseDataLength;\r
874\r
875 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
876\r
877 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
878 *TargetStatus = CommandPacket.TargetStatus;\r
879 *SenseDataLength = CommandPacket.SenseDataLength;\r
880 *DataLength = CommandPacket.OutTransferLength;\r
881\r
882 return Status;\r
883}\r
884\r