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