]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Usb/UsbBotPei/PeiAtapi.c
MdeModulePkg/Usb: Fix various typos
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBotPei / PeiAtapi.c
... / ...
CommitLineData
1/** @file\r
2Pei USB ATAPI command implementations.\r
3\r
4Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
5\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "UsbBotPeim.h"\r
11#include "BotPeim.h"\r
12\r
13#define MAXSENSEKEY 5\r
14\r
15/**\r
16 Sends out ATAPI Inquiry Packet Command to the specified device. This command will\r
17 return INQUIRY data of the device.\r
18\r
19 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
20 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
21\r
22 @retval EFI_SUCCESS Inquiry command completes successfully.\r
23 @retval EFI_DEVICE_ERROR Inquiry command failed.\r
24\r
25**/\r
26EFI_STATUS\r
27PeiUsbInquiry (\r
28 IN EFI_PEI_SERVICES **PeiServices,\r
29 IN PEI_BOT_DEVICE *PeiBotDevice\r
30 )\r
31{\r
32 ATAPI_PACKET_COMMAND Packet;\r
33 EFI_STATUS Status;\r
34 ATAPI_INQUIRY_DATA Idata;\r
35\r
36 //\r
37 // fill command packet\r
38 //\r
39 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
40 ZeroMem (&Idata, sizeof (ATAPI_INQUIRY_DATA));\r
41\r
42 Packet.Inquiry.opcode = ATA_CMD_INQUIRY;\r
43 Packet.Inquiry.page_code = 0;\r
44 Packet.Inquiry.allocation_length = 36;\r
45\r
46 //\r
47 // Send scsi INQUIRY command packet.\r
48 // According to SCSI Primary Commands-2 spec, host only needs to\r
49 // retrieve the first 36 bytes for standard INQUIRY data.\r
50 //\r
51 Status = PeiAtapiCommand (\r
52 PeiServices,\r
53 PeiBotDevice,\r
54 &Packet,\r
55 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
56 &Idata,\r
57 36,\r
58 EfiUsbDataIn,\r
59 2000\r
60 );\r
61\r
62 if (EFI_ERROR (Status)) {\r
63 return EFI_DEVICE_ERROR;\r
64 }\r
65\r
66 if ((Idata.peripheral_type & 0x1f) == 0x05) {\r
67 PeiBotDevice->DeviceType = USBCDROM;\r
68 PeiBotDevice->Media.BlockSize = 0x800;\r
69 PeiBotDevice->Media2.ReadOnly = TRUE;\r
70 PeiBotDevice->Media2.RemovableMedia = TRUE;\r
71 PeiBotDevice->Media2.BlockSize = 0x800;\r
72 } else {\r
73 PeiBotDevice->DeviceType = USBFLOPPY;\r
74 PeiBotDevice->Media.BlockSize = 0x200;\r
75 PeiBotDevice->Media2.ReadOnly = FALSE;\r
76 PeiBotDevice->Media2.RemovableMedia = TRUE;\r
77 PeiBotDevice->Media2.BlockSize = 0x200;\r
78 }\r
79\r
80 return EFI_SUCCESS;\r
81}\r
82\r
83/**\r
84 Sends out ATAPI Test Unit Ready Packet Command to the specified device\r
85 to find out whether device is accessible.\r
86\r
87 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
88 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
89\r
90 @retval EFI_SUCCESS TestUnit command executed successfully.\r
91 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.\r
92\r
93**/\r
94EFI_STATUS\r
95PeiUsbTestUnitReady (\r
96 IN EFI_PEI_SERVICES **PeiServices,\r
97 IN PEI_BOT_DEVICE *PeiBotDevice\r
98 )\r
99{\r
100 ATAPI_PACKET_COMMAND Packet;\r
101 EFI_STATUS Status;\r
102\r
103 //\r
104 // fill command packet\r
105 //\r
106 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
107 Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;\r
108\r
109 //\r
110 // send command packet\r
111 //\r
112 Status = PeiAtapiCommand (\r
113 PeiServices,\r
114 PeiBotDevice,\r
115 &Packet,\r
116 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
117 NULL,\r
118 0,\r
119 EfiUsbNoData,\r
120 2000\r
121 );\r
122\r
123 if (EFI_ERROR (Status)) {\r
124 return EFI_DEVICE_ERROR;\r
125 }\r
126\r
127 return EFI_SUCCESS;\r
128}\r
129\r
130/**\r
131 Sends out ATAPI Request Sense Packet Command to the specified device.\r
132\r
133 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
134 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
135 @param SenseCounts Length of sense buffer.\r
136 @param SenseKeyBuffer Pointer to sense buffer.\r
137\r
138 @retval EFI_SUCCESS Command executed successfully.\r
139 @retval EFI_DEVICE_ERROR Some device errors happen.\r
140\r
141**/\r
142EFI_STATUS\r
143PeiUsbRequestSense (\r
144 IN EFI_PEI_SERVICES **PeiServices,\r
145 IN PEI_BOT_DEVICE *PeiBotDevice,\r
146 OUT UINTN *SenseCounts,\r
147 IN UINT8 *SenseKeyBuffer\r
148 )\r
149{\r
150 EFI_STATUS Status;\r
151 ATAPI_PACKET_COMMAND Packet;\r
152 UINT8 *Ptr;\r
153 BOOLEAN SenseReq;\r
154 ATAPI_REQUEST_SENSE_DATA *Sense;\r
155\r
156 *SenseCounts = 0;\r
157\r
158 //\r
159 // fill command packet for Request Sense Packet Command\r
160 //\r
161 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
162 Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE;\r
163 Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA);\r
164\r
165 Ptr = SenseKeyBuffer;\r
166\r
167 SenseReq = TRUE;\r
168\r
169 //\r
170 // request sense data from device continuously\r
171 // until no sense data exists in the device.\r
172 //\r
173 while (SenseReq) {\r
174 Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr;\r
175\r
176 //\r
177 // send out Request Sense Packet Command and get one Sense\r
178 // data form device.\r
179 //\r
180 Status = PeiAtapiCommand (\r
181 PeiServices,\r
182 PeiBotDevice,\r
183 &Packet,\r
184 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
185 (VOID *) Ptr,\r
186 sizeof (ATAPI_REQUEST_SENSE_DATA),\r
187 EfiUsbDataIn,\r
188 2000\r
189 );\r
190\r
191 //\r
192 // failed to get Sense data\r
193 //\r
194 if (EFI_ERROR (Status)) {\r
195 if (*SenseCounts == 0) {\r
196 return EFI_DEVICE_ERROR;\r
197 } else {\r
198 return EFI_SUCCESS;\r
199 }\r
200 }\r
201\r
202 if (Sense->sense_key != ATA_SK_NO_SENSE) {\r
203\r
204 Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA);\r
205 //\r
206 // Ptr is byte based pointer\r
207 //\r
208 (*SenseCounts)++;\r
209\r
210 if (*SenseCounts == MAXSENSEKEY) {\r
211 break;\r
212 }\r
213\r
214 } else {\r
215 //\r
216 // when no sense key, skip out the loop\r
217 //\r
218 SenseReq = FALSE;\r
219 }\r
220 }\r
221\r
222 return EFI_SUCCESS;\r
223}\r
224\r
225/**\r
226 Sends out ATAPI Read Capacity Packet Command to the specified device.\r
227 This command will return the information regarding the capacity of the\r
228 media in the device.\r
229\r
230 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
231 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
232\r
233 @retval EFI_SUCCESS Command executed successfully.\r
234 @retval EFI_DEVICE_ERROR Some device errors happen.\r
235\r
236**/\r
237EFI_STATUS\r
238PeiUsbReadCapacity (\r
239 IN EFI_PEI_SERVICES **PeiServices,\r
240 IN PEI_BOT_DEVICE *PeiBotDevice\r
241 )\r
242{\r
243 EFI_STATUS Status;\r
244 ATAPI_PACKET_COMMAND Packet;\r
245 ATAPI_READ_CAPACITY_DATA Data;\r
246 UINT32 LastBlock;\r
247\r
248 ZeroMem (&Data, sizeof (ATAPI_READ_CAPACITY_DATA));\r
249 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
250\r
251 Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;\r
252\r
253 //\r
254 // send command packet\r
255 //\r
256 Status = PeiAtapiCommand (\r
257 PeiServices,\r
258 PeiBotDevice,\r
259 &Packet,\r
260 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
261 (VOID *) &Data,\r
262 sizeof (ATAPI_READ_CAPACITY_DATA),\r
263 EfiUsbDataIn,\r
264 2000\r
265 );\r
266\r
267 if (EFI_ERROR (Status)) {\r
268 return EFI_DEVICE_ERROR;\r
269 }\r
270 LastBlock = ((UINT32) Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;\r
271\r
272 if (LastBlock == 0xFFFFFFFF) {\r
273 DEBUG ((EFI_D_INFO, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));\r
274 }\r
275\r
276 PeiBotDevice->Media.LastBlock = LastBlock;\r
277 PeiBotDevice->Media.MediaPresent = TRUE;\r
278\r
279 PeiBotDevice->Media2.LastBlock = LastBlock;\r
280 PeiBotDevice->Media2.MediaPresent = TRUE;\r
281\r
282 return EFI_SUCCESS;\r
283}\r
284\r
285/**\r
286 Sends out ATAPI Read Format Capacity Data Command to the specified device.\r
287 This command will return the information regarding the capacity of the\r
288 media in the device.\r
289\r
290 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
291 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
292\r
293 @retval EFI_SUCCESS Command executed successfully.\r
294 @retval EFI_DEVICE_ERROR Some device errors happen.\r
295\r
296**/\r
297EFI_STATUS\r
298PeiUsbReadFormattedCapacity (\r
299 IN EFI_PEI_SERVICES **PeiServices,\r
300 IN PEI_BOT_DEVICE *PeiBotDevice\r
301 )\r
302{\r
303 EFI_STATUS Status;\r
304 ATAPI_PACKET_COMMAND Packet;\r
305 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData;\r
306 UINT32 LastBlock;\r
307\r
308 ZeroMem (&FormatData, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA));\r
309 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
310\r
311 Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY;\r
312 Packet.ReadFormatCapacity.allocation_length_lo = 12;\r
313\r
314 //\r
315 // send command packet\r
316 //\r
317 Status = PeiAtapiCommand (\r
318 PeiServices,\r
319 PeiBotDevice,\r
320 &Packet,\r
321 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
322 (VOID *) &FormatData,\r
323 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),\r
324 EfiUsbDataIn,\r
325 2000\r
326 );\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 return EFI_DEVICE_ERROR;\r
330 }\r
331\r
332 if (FormatData.DesCode == 3) {\r
333 //\r
334 // Media is not present\r
335 //\r
336 PeiBotDevice->Media.MediaPresent = FALSE;\r
337 PeiBotDevice->Media.LastBlock = 0;\r
338 PeiBotDevice->Media2.MediaPresent = FALSE;\r
339 PeiBotDevice->Media2.LastBlock = 0;\r
340\r
341 } else {\r
342 LastBlock = ((UINT32) FormatData.LastLba3 << 24) | (FormatData.LastLba2 << 16) | (FormatData.LastLba1 << 8) | FormatData.LastLba0;\r
343 if (LastBlock == 0xFFFFFFFF) {\r
344 DEBUG ((EFI_D_INFO, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));\r
345 }\r
346\r
347 PeiBotDevice->Media.LastBlock = LastBlock;\r
348\r
349 PeiBotDevice->Media.LastBlock--;\r
350\r
351 PeiBotDevice->Media.MediaPresent = TRUE;\r
352\r
353 PeiBotDevice->Media2.MediaPresent = TRUE;\r
354 PeiBotDevice->Media2.LastBlock = PeiBotDevice->Media.LastBlock;\r
355 }\r
356\r
357 return EFI_SUCCESS;\r
358}\r
359\r
360/**\r
361 Execute Read(10) ATAPI command on a specific SCSI target.\r
362\r
363 Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.\r
364\r
365 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
366 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.\r
367 @param Buffer The pointer to data buffer.\r
368 @param Lba The start logic block address of reading.\r
369 @param NumberOfBlocks The block number of reading.\r
370\r
371 @retval EFI_SUCCESS Command executed successfully.\r
372 @retval EFI_DEVICE_ERROR Some device errors happen.\r
373\r
374**/\r
375EFI_STATUS\r
376PeiUsbRead10 (\r
377 IN EFI_PEI_SERVICES **PeiServices,\r
378 IN PEI_BOT_DEVICE *PeiBotDevice,\r
379 IN VOID *Buffer,\r
380 IN EFI_PEI_LBA Lba,\r
381 IN UINTN NumberOfBlocks\r
382 )\r
383{\r
384 ATAPI_PACKET_COMMAND Packet;\r
385 ATAPI_READ10_CMD *Read10Packet;\r
386 UINT16 MaxBlock;\r
387 UINT16 BlocksRemaining;\r
388 UINT16 SectorCount;\r
389 UINT32 Lba32;\r
390 UINT32 BlockSize;\r
391 UINT32 ByteCount;\r
392 VOID *PtrBuffer;\r
393 EFI_STATUS Status;\r
394 UINT16 TimeOut;\r
395\r
396 //\r
397 // prepare command packet for the Inquiry Packet Command.\r
398 //\r
399 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
400 Read10Packet = &Packet.Read10;\r
401 Lba32 = (UINT32) Lba;\r
402 PtrBuffer = Buffer;\r
403\r
404 BlockSize = (UINT32) PeiBotDevice->Media.BlockSize;\r
405\r
406 MaxBlock = (UINT16) (65535 / BlockSize);\r
407 BlocksRemaining = (UINT16) NumberOfBlocks;\r
408\r
409 Status = EFI_SUCCESS;\r
410 while (BlocksRemaining > 0) {\r
411\r
412 if (BlocksRemaining <= MaxBlock) {\r
413\r
414 SectorCount = BlocksRemaining;\r
415\r
416 } else {\r
417\r
418 SectorCount = MaxBlock;\r
419 }\r
420 //\r
421 // fill the Packet data structure\r
422 //\r
423 Read10Packet->opcode = ATA_CMD_READ_10;\r
424\r
425 //\r
426 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.\r
427 // Lba0 is MSB, Lba3 is LSB\r
428 //\r
429 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);\r
430 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);\r
431 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);\r
432 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);\r
433\r
434 //\r
435 // TranLen0 ~ TranLen1 specify the transfer length in block unit.\r
436 // TranLen0 is MSB, TranLen is LSB\r
437 //\r
438 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);\r
439 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);\r
440\r
441 ByteCount = SectorCount * BlockSize;\r
442\r
443 TimeOut = (UINT16) (SectorCount * 2000);\r
444\r
445 //\r
446 // send command packet\r
447 //\r
448 Status = PeiAtapiCommand (\r
449 PeiServices,\r
450 PeiBotDevice,\r
451 &Packet,\r
452 (UINT8) sizeof (ATAPI_PACKET_COMMAND),\r
453 (VOID *) PtrBuffer,\r
454 ByteCount,\r
455 EfiUsbDataIn,\r
456 TimeOut\r
457 );\r
458\r
459 if (Status != EFI_SUCCESS) {\r
460 return Status;\r
461 }\r
462\r
463 Lba32 += SectorCount;\r
464 PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;\r
465 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);\r
466 }\r
467\r
468 return Status;\r
469}\r
470\r
471/**\r
472 Check if there is media according to sense data.\r
473\r
474 @param SenseData Pointer to sense data.\r
475 @param SenseCounts Count of sense data.\r
476\r
477 @retval TRUE No media\r
478 @retval FALSE Media exists\r
479\r
480**/\r
481BOOLEAN\r
482IsNoMedia (\r
483 IN ATAPI_REQUEST_SENSE_DATA *SenseData,\r
484 IN UINTN SenseCounts\r
485 )\r
486{\r
487 ATAPI_REQUEST_SENSE_DATA *SensePtr;\r
488 UINTN Index;\r
489 BOOLEAN NoMedia;\r
490\r
491 NoMedia = FALSE;\r
492 SensePtr = SenseData;\r
493\r
494 for (Index = 0; Index < SenseCounts; Index++) {\r
495\r
496 switch (SensePtr->sense_key) {\r
497\r
498 case ATA_SK_NOT_READY:\r
499 switch (SensePtr->addnl_sense_code) {\r
500 //\r
501 // if no media, fill IdeDev parameter with specific info.\r
502 //\r
503 case ATA_ASC_NO_MEDIA:\r
504 NoMedia = TRUE;\r
505 break;\r
506\r
507 default:\r
508 break;\r
509 }\r
510 break;\r
511\r
512 default:\r
513 break;\r
514 }\r
515\r
516 SensePtr++;\r
517 }\r
518\r
519 return NoMedia;\r
520}\r
521\r
522/**\r
523 Check if there is media error according to sense data.\r
524\r
525 @param SenseData Pointer to sense data.\r
526 @param SenseCounts Count of sense data.\r
527\r
528 @retval TRUE Media error\r
529 @retval FALSE No media error\r
530\r
531**/\r
532BOOLEAN\r
533IsMediaError (\r
534 IN ATAPI_REQUEST_SENSE_DATA *SenseData,\r
535 IN UINTN SenseCounts\r
536 )\r
537{\r
538 ATAPI_REQUEST_SENSE_DATA *SensePtr;\r
539 UINTN Index;\r
540 BOOLEAN Error;\r
541\r
542 SensePtr = SenseData;\r
543 Error = FALSE;\r
544\r
545 for (Index = 0; Index < SenseCounts; Index++) {\r
546\r
547 switch (SensePtr->sense_key) {\r
548 //\r
549 // Medium error case\r
550 //\r
551 case ATA_SK_MEDIUM_ERROR:\r
552 switch (SensePtr->addnl_sense_code) {\r
553 case ATA_ASC_MEDIA_ERR1:\r
554 //\r
555 // fall through\r
556 //\r
557 case ATA_ASC_MEDIA_ERR2:\r
558 //\r
559 // fall through\r
560 //\r
561 case ATA_ASC_MEDIA_ERR3:\r
562 //\r
563 // fall through\r
564 //\r
565 case ATA_ASC_MEDIA_ERR4:\r
566 Error = TRUE;\r
567 break;\r
568\r
569 default:\r
570 break;\r
571 }\r
572\r
573 break;\r
574\r
575 //\r
576 // Medium upside-down case\r
577 //\r
578 case ATA_SK_NOT_READY:\r
579 switch (SensePtr->addnl_sense_code) {\r
580 case ATA_ASC_MEDIA_UPSIDE_DOWN:\r
581 Error = TRUE;\r
582 break;\r
583\r
584 default:\r
585 break;\r
586 }\r
587 break;\r
588\r
589 default:\r
590 break;\r
591 }\r
592\r
593 SensePtr++;\r
594 }\r
595\r
596 return Error;\r
597}\r
598\r
599/**\r
600 Check if media is changed according to sense data.\r
601\r
602 @param SenseData Pointer to sense data.\r
603 @param SenseCounts Count of sense data.\r
604\r
605 @retval TRUE There is media change event.\r
606 @retval FALSE media is NOT changed.\r
607\r
608**/\r
609BOOLEAN\r
610IsMediaChange (\r
611 IN ATAPI_REQUEST_SENSE_DATA *SenseData,\r
612 IN UINTN SenseCounts\r
613 )\r
614{\r
615 ATAPI_REQUEST_SENSE_DATA *SensePtr;\r
616 UINTN Index;\r
617 BOOLEAN MediaChange;\r
618\r
619 MediaChange = FALSE;\r
620\r
621 SensePtr = SenseData;\r
622\r
623 for (Index = 0; Index < SenseCounts; Index++) {\r
624 //\r
625 // catch media change sense key and addition sense data\r
626 //\r
627 switch (SensePtr->sense_key) {\r
628 case ATA_SK_UNIT_ATTENTION:\r
629 switch (SensePtr->addnl_sense_code) {\r
630 case ATA_ASC_MEDIA_CHANGE:\r
631 MediaChange = TRUE;\r
632 break;\r
633\r
634 default:\r
635 break;\r
636 }\r
637 break;\r
638\r
639 default:\r
640 break;\r
641 }\r
642\r
643 SensePtr++;\r
644 }\r
645\r
646 return MediaChange;\r
647}\r