1 /** @file
2   This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces
3   for managed ATA controllers.
4 
5   Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "AtaAtapiPassThru.h"
11 
12 //
13 //  EFI_DRIVER_BINDING_PROTOCOL instance
14 //
15 EFI_DRIVER_BINDING_PROTOCOL gAtaAtapiPassThruDriverBinding = {
16   AtaAtapiPassThruSupported,
17   AtaAtapiPassThruStart,
18   AtaAtapiPassThruStop,
19   0x10,
20   NULL,
21   NULL
22 };
23 
24 ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = {
25   ATA_ATAPI_PASS_THRU_SIGNATURE,
26   0,                  // Controller Handle
27   NULL,               // PciIo Protocol
28   NULL,               // IdeControllerInit Protocol
29   {                   // AtaPassThruMode
30     //
31     // According to UEFI2.3 spec Section 12.10, Drivers for non-RAID ATA controllers should set
32     // both EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL and EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL
33     // bits.
34     // Note that the driver doesn't support AtaPassThru non blocking I/O.
35     //
36     EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
37     //
38     // IoAlign
39     //
40     sizeof (UINTN)
41   },
42   {                   // AtaPassThru
43     NULL,
44     AtaPassThruPassThru,
45     AtaPassThruGetNextPort,
46     AtaPassThruGetNextDevice,
47     AtaPassThruBuildDevicePath,
48     AtaPassThruGetDevice,
49     AtaPassThruResetPort,
50     AtaPassThruResetDevice
51   },
52   {                   // ExtScsiPassThruMode
53     //
54     // AdapterId
55     //
56     0,
57     //
58     // According to UEFI2.3 spec Section 14.7, Drivers for non-RAID SCSI controllers should set
59     // both EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL and EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL
60     // bits.
61     // Note that the driver doesn't support ExtScsiPassThru non blocking I/O.
62     //
63     EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL,
64     //
65     // IoAlign
66     //
67     sizeof (UINTN)
68   },
69   {                   // ExtScsiPassThru
70     NULL,
71     ExtScsiPassThruPassThru,
72     ExtScsiPassThruGetNextTargetLun,
73     ExtScsiPassThruBuildDevicePath,
74     ExtScsiPassThruGetTargetLun,
75     ExtScsiPassThruResetChannel,
76     ExtScsiPassThruResetTargetLun,
77     ExtScsiPassThruGetNextTarget
78   },
79   EfiAtaUnknownMode,  // Work Mode
80   {                   // IdeRegisters
81     {0},
82     {0}
83   },
84   {                   // AhciRegisters
85     0
86   },
87   {                   // DeviceList
88     NULL,
89     NULL
90   },
91   0,                  // EnabledPciAttributes
92   0,                  // OriginalAttributes
93   0,                  // PreviousPort
94   0,                  // PreviousPortMultiplier
95   0,                  // PreviousTargetId
96   0,                  // PreviousLun
97   NULL,               // Timer event
98   {                   // NonBlocking TaskList
99     NULL,
100     NULL
101   }
102 };
103 
104 ATAPI_DEVICE_PATH    mAtapiDevicePathTemplate = {
105   {
106     MESSAGING_DEVICE_PATH,
107     MSG_ATAPI_DP,
108     {
109       (UINT8) (sizeof (ATAPI_DEVICE_PATH)),
110       (UINT8) ((sizeof (ATAPI_DEVICE_PATH)) >> 8)
111     }
112   },
113   0,
114   0,
115   0
116 };
117 
118 SATA_DEVICE_PATH    mSataDevicePathTemplate = {
119   {
120     MESSAGING_DEVICE_PATH,
121     MSG_SATA_DP,
122     {
123       (UINT8) (sizeof (SATA_DEVICE_PATH)),
124       (UINT8) ((sizeof (SATA_DEVICE_PATH)) >> 8)
125     }
126   },
127   0,
128   0,
129   0
130 };
131 
132 UINT8 mScsiId[TARGET_MAX_BYTES] = {
133   0xFF, 0xFF, 0xFF, 0xFF,
134   0xFF, 0xFF, 0xFF, 0xFF,
135   0xFF, 0xFF, 0xFF, 0xFF,
136   0xFF, 0xFF, 0xFF, 0xFF
137 };
138 
139 EDKII_ATA_ATAPI_POLICY_PROTOCOL *mAtaAtapiPolicy;
140 EDKII_ATA_ATAPI_POLICY_PROTOCOL mDefaultAtaAtapiPolicy = {
141   EDKII_ATA_ATAPI_POLICY_VERSION,
142   2,  // PuisEnable
143   0,  // DeviceSleepEnable
144   0,  // AggressiveDeviceSleepEnable
145   0   // Reserved
146 };
147 
148 /**
149   Sends an ATA command to an ATA device that is attached to the ATA controller. This function
150   supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
151   and the non-blocking I/O functionality is optional.
152 
153   @param[in]      Port               The port number of the ATA device to send the command.
154   @param[in]      PortMultiplierPort The port multiplier port number of the ATA device to send the command.
155                                      If there is no port multiplier, then specify 0xFFFF.
156   @param[in, out] Packet             A pointer to the ATA command to send to the ATA device specified by Port
157                                      and PortMultiplierPort.
158   @param[in]      Instance           Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.
159   @param[in]      Task               Optional. Pointer to the ATA_NONBLOCK_TASK
160                                      used by non-blocking mode.
161 
162   @retval EFI_SUCCESS                The ATA command was sent by the host. For
163                                      bi-directional commands, InTransferLength bytes
164                                      were transferred from InDataBuffer. For
165                                      write and bi-directional commands, OutTransferLength
166                                      bytes were transferred by OutDataBuffer.
167   @retval EFI_BAD_BUFFER_SIZE        The ATA command was not executed. The number
168                                      of bytes that could be transferred is returned
169                                      in InTransferLength. For write and bi-directional
170                                      commands, OutTransferLength bytes were transferred
171                                      by OutDataBuffer.
172   @retval EFI_NOT_READY              The ATA command could not be sent because
173                                      there are too many ATA commands already
174                                      queued. The caller may retry again later.
175   @retval EFI_DEVICE_ERROR           A device error occurred while attempting
176                                      to send the ATA command.
177   @retval EFI_INVALID_PARAMETER      Port, PortMultiplierPort, or the contents
178                                      of Acb are invalid. The ATA command was
179                                      not sent, so no additional status information
180                                      is available.
181 
182 **/
183 EFI_STATUS
184 EFIAPI
AtaPassThruPassThruExecute(IN UINT16 Port,IN UINT16 PortMultiplierPort,IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET * Packet,IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance,IN ATA_NONBLOCK_TASK * Task OPTIONAL)185 AtaPassThruPassThruExecute (
186   IN     UINT16                           Port,
187   IN     UINT16                           PortMultiplierPort,
188   IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
189   IN     ATA_ATAPI_PASS_THRU_INSTANCE     *Instance,
190   IN     ATA_NONBLOCK_TASK                *Task OPTIONAL
191   )
192 {
193   EFI_ATA_PASS_THRU_CMD_PROTOCOL  Protocol;
194   EFI_ATA_HC_WORK_MODE            Mode;
195   EFI_STATUS                      Status;
196 
197   Protocol = Packet->Protocol;
198 
199   Mode = Instance->Mode;
200   switch (Mode) {
201     case EfiAtaIdeMode:
202       //
203       // Reassign IDE mode io port registers' base addresses
204       //
205       Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
206 
207       if (EFI_ERROR (Status)) {
208         return Status;
209       }
210 
211       switch (Protocol) {
212         case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
213           Status = AtaNonDataCommandIn (
214                      Instance->PciIo,
215                      &Instance->IdeRegisters[Port],
216                      Packet->Acb,
217                      Packet->Asb,
218                      Packet->Timeout,
219                      Task
220                      );
221           break;
222         case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
223           Status = AtaPioDataInOut (
224                      Instance->PciIo,
225                      &Instance->IdeRegisters[Port],
226                      Packet->InDataBuffer,
227                      Packet->InTransferLength,
228                      TRUE,
229                      Packet->Acb,
230                      Packet->Asb,
231                      Packet->Timeout,
232                      Task
233                      );
234           break;
235         case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
236           Status = AtaPioDataInOut (
237                      Instance->PciIo,
238                      &Instance->IdeRegisters[Port],
239                      Packet->OutDataBuffer,
240                      Packet->OutTransferLength,
241                      FALSE,
242                      Packet->Acb,
243                      Packet->Asb,
244                      Packet->Timeout,
245                      Task
246                      );
247           break;
248         case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
249           Status = AtaUdmaInOut (
250                      Instance,
251                      &Instance->IdeRegisters[Port],
252                      TRUE,
253                      Packet->InDataBuffer,
254                      Packet->InTransferLength,
255                      Packet->Acb,
256                      Packet->Asb,
257                      Packet->Timeout,
258                      Task
259                      );
260           break;
261         case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
262           Status = AtaUdmaInOut (
263                      Instance,
264                      &Instance->IdeRegisters[Port],
265                      FALSE,
266                      Packet->OutDataBuffer,
267                      Packet->OutTransferLength,
268                      Packet->Acb,
269                      Packet->Asb,
270                      Packet->Timeout,
271                      Task
272                      );
273           break;
274         default :
275           return EFI_UNSUPPORTED;
276       }
277       break;
278     case EfiAtaAhciMode :
279       if (PortMultiplierPort == 0xFFFF) {
280         //
281         // If there is no port multiplier, PortMultiplierPort will be 0xFFFF
282         // according to UEFI spec. Here, we convert its value to 0 to follow
283         // AHCI spec.
284         //
285         PortMultiplierPort = 0;
286       }
287       switch (Protocol) {
288         case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
289           Status = AhciNonDataTransfer (
290                      Instance->PciIo,
291                      &Instance->AhciRegisters,
292                      (UINT8)Port,
293                      (UINT8)PortMultiplierPort,
294                      NULL,
295                      0,
296                      Packet->Acb,
297                      Packet->Asb,
298                      Packet->Timeout,
299                      Task
300                      );
301           break;
302         case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
303           Status = AhciPioTransfer (
304                      Instance->PciIo,
305                      &Instance->AhciRegisters,
306                      (UINT8)Port,
307                      (UINT8)PortMultiplierPort,
308                      NULL,
309                      0,
310                      TRUE,
311                      Packet->Acb,
312                      Packet->Asb,
313                      Packet->InDataBuffer,
314                      Packet->InTransferLength,
315                      Packet->Timeout,
316                      Task
317                      );
318           break;
319         case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
320           Status = AhciPioTransfer (
321                      Instance->PciIo,
322                      &Instance->AhciRegisters,
323                      (UINT8)Port,
324                      (UINT8)PortMultiplierPort,
325                      NULL,
326                      0,
327                      FALSE,
328                      Packet->Acb,
329                      Packet->Asb,
330                      Packet->OutDataBuffer,
331                      Packet->OutTransferLength,
332                      Packet->Timeout,
333                      Task
334                      );
335           break;
336         case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
337           Status = AhciDmaTransfer (
338                      Instance,
339                      &Instance->AhciRegisters,
340                      (UINT8)Port,
341                      (UINT8)PortMultiplierPort,
342                      NULL,
343                      0,
344                      TRUE,
345                      Packet->Acb,
346                      Packet->Asb,
347                      Packet->InDataBuffer,
348                      Packet->InTransferLength,
349                      Packet->Timeout,
350                      Task
351                      );
352           break;
353         case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
354           Status = AhciDmaTransfer (
355                      Instance,
356                      &Instance->AhciRegisters,
357                      (UINT8)Port,
358                      (UINT8)PortMultiplierPort,
359                      NULL,
360                      0,
361                      FALSE,
362                      Packet->Acb,
363                      Packet->Asb,
364                      Packet->OutDataBuffer,
365                      Packet->OutTransferLength,
366                      Packet->Timeout,
367                      Task
368                      );
369           break;
370         default :
371           return EFI_UNSUPPORTED;
372       }
373       break;
374 
375     default:
376       Status = EFI_DEVICE_ERROR;
377       break;
378   }
379 
380   return Status;
381 }
382 
383 /**
384   Call back function when the timer event is signaled.
385 
386   @param[in]  Event     The Event this notify function registered to.
387   @param[in]  Context   Pointer to the context data registered to the
388                         Event.
389 
390 **/
391 VOID
392 EFIAPI
AsyncNonBlockingTransferRoutine(EFI_EVENT Event,VOID * Context)393 AsyncNonBlockingTransferRoutine (
394   EFI_EVENT  Event,
395   VOID*      Context
396   )
397 {
398   LIST_ENTRY                   *Entry;
399   LIST_ENTRY                   *EntryHeader;
400   ATA_NONBLOCK_TASK            *Task;
401   EFI_STATUS                   Status;
402   ATA_ATAPI_PASS_THRU_INSTANCE *Instance;
403 
404   Instance   = (ATA_ATAPI_PASS_THRU_INSTANCE *) Context;
405   EntryHeader = &Instance->NonBlockingTaskList;
406   //
407   // Get the Taks from the Taks List and execute it, until there is
408   // no task in the list or the device is busy with task (EFI_NOT_READY).
409   //
410   while (TRUE) {
411     if (!IsListEmpty (EntryHeader)) {
412       Entry = GetFirstNode (EntryHeader);
413       Task  = ATA_NON_BLOCK_TASK_FROM_ENTRY (Entry);
414     } else {
415       return;
416     }
417 
418     Status = AtaPassThruPassThruExecute (
419                Task->Port,
420                Task->PortMultiplier,
421                Task->Packet,
422                Instance,
423                Task
424                );
425 
426     //
427     // If the data transfer meet a error, remove all tasks in the list since these tasks are
428     // associated with one task from Ata Bus and signal the event with error status.
429     //
430     if ((Status != EFI_NOT_READY) && (Status != EFI_SUCCESS)) {
431       DestroyAsynTaskList (Instance, TRUE);
432       break;
433     }
434 
435     //
436     // For Non blocking mode, the Status of EFI_NOT_READY means the operation
437     // is not finished yet. Otherwise the operation is successful.
438     //
439     if (Status == EFI_NOT_READY) {
440       break;
441     } else {
442       RemoveEntryList (&Task->Link);
443       gBS->SignalEvent (Task->Event);
444       FreePool (Task);
445     }
446   }
447 }
448 
449 /**
450   The Entry Point of module.
451 
452   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
453   @param[in] SystemTable    A pointer to the EFI System Table.
454 
455   @retval EFI_SUCCESS       The entry point is executed successfully.
456   @retval other             Some error occurs when executing this entry point.
457 
458 **/
459 EFI_STATUS
460 EFIAPI
InitializeAtaAtapiPassThru(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)461 InitializeAtaAtapiPassThru (
462   IN EFI_HANDLE           ImageHandle,
463   IN EFI_SYSTEM_TABLE     *SystemTable
464   )
465 {
466   EFI_STATUS              Status;
467 
468   //
469   // Install driver model protocol(s).
470   //
471   Status = EfiLibInstallDriverBindingComponentName2 (
472              ImageHandle,
473              SystemTable,
474              &gAtaAtapiPassThruDriverBinding,
475              ImageHandle,
476              &gAtaAtapiPassThruComponentName,
477              &gAtaAtapiPassThruComponentName2
478              );
479   ASSERT_EFI_ERROR (Status);
480 
481   return Status;
482 }
483 
484 /**
485   Tests to see if this driver supports a given controller. If a child device is provided,
486   it further tests to see if this driver supports creating a handle for the specified child device.
487 
488   This function checks to see if the driver specified by This supports the device specified by
489   ControllerHandle. Drivers will typically use the device path attached to
490   ControllerHandle and/or the services from the bus I/O abstraction attached to
491   ControllerHandle to determine if the driver supports ControllerHandle. This function
492   may be called many times during platform initialization. In order to reduce boot times, the tests
493   performed by this function must be very small, and take as little time as possible to execute. This
494   function must not change the state of any hardware devices, and this function must be aware that the
495   device specified by ControllerHandle may already be managed by the same driver or a
496   different driver. This function must match its calls to AllocatePages() with FreePages(),
497   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
498   Because ControllerHandle may have been previously started by the same driver, if a protocol is
499   already in the opened state, then it must not be closed with CloseProtocol(). This is required
500   to guarantee the state of ControllerHandle is not modified by this function.
501 
502   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
503   @param[in]  ControllerHandle     The handle of the controller to test. This handle
504                                    must support a protocol interface that supplies
505                                    an I/O abstraction to the driver.
506   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
507                                    parameter is ignored by device drivers, and is optional for bus
508                                    drivers. For bus drivers, if this parameter is not NULL, then
509                                    the bus driver must determine if the bus controller specified
510                                    by ControllerHandle and the child controller specified
511                                    by RemainingDevicePath are both supported by this
512                                    bus driver.
513 
514   @retval EFI_SUCCESS              The device specified by ControllerHandle and
515                                    RemainingDevicePath is supported by the driver specified by This.
516   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
517                                    RemainingDevicePath is already being managed by the driver
518                                    specified by This.
519   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
520                                    RemainingDevicePath is already being managed by a different
521                                    driver or an application that requires exclusive access.
522                                    Currently not implemented.
523   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
524                                    RemainingDevicePath is not supported by the driver specified by This.
525 **/
526 EFI_STATUS
527 EFIAPI
AtaAtapiPassThruSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)528 AtaAtapiPassThruSupported (
529   IN EFI_DRIVER_BINDING_PROTOCOL       *This,
530   IN EFI_HANDLE                        Controller,
531   IN EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath
532   )
533 {
534   EFI_STATUS                        Status;
535   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
536   EFI_PCI_IO_PROTOCOL               *PciIo;
537   PCI_TYPE00                        PciData;
538   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeControllerInit;
539 
540   //
541   // SATA Controller is a device driver, and should ingore the
542   // "RemainingDevicePath" according to UEFI spec
543   //
544   Status = gBS->OpenProtocol (
545                   Controller,
546                   &gEfiDevicePathProtocolGuid,
547                   (VOID *) &ParentDevicePath,
548                   This->DriverBindingHandle,
549                   Controller,
550                   EFI_OPEN_PROTOCOL_BY_DRIVER
551                   );
552   if (EFI_ERROR (Status)) {
553     //
554     // EFI_ALREADY_STARTED is also an error
555     //
556     return Status;
557   }
558   //
559   // Close the protocol because we don't use it here
560   //
561   gBS->CloseProtocol (
562                   Controller,
563                   &gEfiDevicePathProtocolGuid,
564                   This->DriverBindingHandle,
565                   Controller
566                   );
567 
568   Status = gBS->OpenProtocol (
569                   Controller,
570                   &gEfiIdeControllerInitProtocolGuid,
571                   (VOID **) &IdeControllerInit,
572                   This->DriverBindingHandle,
573                   Controller,
574                   EFI_OPEN_PROTOCOL_BY_DRIVER
575                   );
576 
577   if (EFI_ERROR (Status)) {
578     //
579     // EFI_ALREADY_STARTED is also an error
580     //
581     return Status;
582   }
583 
584   //
585   // Close the I/O Abstraction(s) used to perform the supported test
586   //
587   gBS->CloseProtocol (
588         Controller,
589         &gEfiIdeControllerInitProtocolGuid,
590         This->DriverBindingHandle,
591         Controller
592         );
593 
594   //
595   // Now test the EfiPciIoProtocol
596   //
597   Status = gBS->OpenProtocol (
598                   Controller,
599                   &gEfiPciIoProtocolGuid,
600                   (VOID **) &PciIo,
601                   This->DriverBindingHandle,
602                   Controller,
603                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
604                   );
605   if (EFI_ERROR (Status)) {
606     return Status;
607   }
608   //
609   // Now further check the PCI header: Base class (offset 0x0B) and
610   // Sub Class (offset 0x0A). This controller should be an ATA controller
611   //
612   Status = PciIo->Pci.Read (
613                         PciIo,
614                         EfiPciIoWidthUint8,
615                         PCI_CLASSCODE_OFFSET,
616                         sizeof (PciData.Hdr.ClassCode),
617                         PciData.Hdr.ClassCode
618                         );
619   if (EFI_ERROR (Status)) {
620     return EFI_UNSUPPORTED;
621   }
622 
623   if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {
624     return EFI_SUCCESS;
625   }
626 
627   return EFI_UNSUPPORTED;
628 }
629 
630 /**
631   Starts a device controller or a bus controller.
632 
633   The Start() function is designed to be invoked from the EFI boot service ConnectController().
634   As a result, much of the error checking on the parameters to Start() has been moved into this
635   common boot service. It is legal to call Start() from other locations,
636   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
637   1. ControllerHandle must be a valid EFI_HANDLE.
638   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
639      EFI_DEVICE_PATH_PROTOCOL.
640   3. Prior to calling Start(), the Supported() function for the driver specified by This must
641      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
642 
643   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
644   @param[in]  ControllerHandle     The handle of the controller to start. This handle
645                                    must support a protocol interface that supplies
646                                    an I/O abstraction to the driver.
647   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
648                                    parameter is ignored by device drivers, and is optional for bus
649                                    drivers. For a bus driver, if this parameter is NULL, then handles
650                                    for all the children of Controller are created by this driver.
651                                    If this parameter is not NULL and the first Device Path Node is
652                                    not the End of Device Path Node, then only the handle for the
653                                    child device specified by the first Device Path Node of
654                                    RemainingDevicePath is created by this driver.
655                                    If the first Device Path Node of RemainingDevicePath is
656                                    the End of Device Path Node, no child handle is created by this
657                                    driver.
658 
659   @retval EFI_SUCCESS              The device was started.
660   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
661   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
662   @retval Others                   The driver failded to start the device.
663 
664 **/
665 EFI_STATUS
666 EFIAPI
AtaAtapiPassThruStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)667 AtaAtapiPassThruStart (
668   IN EFI_DRIVER_BINDING_PROTOCOL        *This,
669   IN EFI_HANDLE                         Controller,
670   IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
671   )
672 {
673   EFI_STATUS                        Status;
674   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeControllerInit;
675   ATA_ATAPI_PASS_THRU_INSTANCE      *Instance;
676   EFI_PCI_IO_PROTOCOL               *PciIo;
677   UINT64                            EnabledPciAttributes;
678   UINT64                            OriginalPciAttributes;
679 
680   Status                = EFI_SUCCESS;
681   IdeControllerInit     = NULL;
682   Instance              = NULL;
683   OriginalPciAttributes = 0;
684 
685   DEBUG ((EFI_D_INFO, "==AtaAtapiPassThru Start== Controller = %x\n", Controller));
686 
687   Status  = gBS->OpenProtocol (
688                    Controller,
689                    &gEfiIdeControllerInitProtocolGuid,
690                    (VOID **) &IdeControllerInit,
691                    This->DriverBindingHandle,
692                    Controller,
693                    EFI_OPEN_PROTOCOL_BY_DRIVER
694                    );
695 
696   if (EFI_ERROR (Status)) {
697     DEBUG ((EFI_D_ERROR, "Open Ide_Controller_Init Error, Status=%r", Status));
698     goto ErrorExit;
699   }
700 
701   Status = gBS->OpenProtocol (
702                   Controller,
703                   &gEfiPciIoProtocolGuid,
704                   (VOID **) &PciIo,
705                   This->DriverBindingHandle,
706                   Controller,
707                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
708                   );
709   if (EFI_ERROR (Status)) {
710     DEBUG ((EFI_D_ERROR, "Get Pci_Io Protocol Error, Status=%r", Status));
711     goto ErrorExit;
712   }
713 
714   Status = PciIo->Attributes (
715                     PciIo,
716                     EfiPciIoAttributeOperationGet,
717                     0,
718                     &OriginalPciAttributes
719                     );
720 
721   if (EFI_ERROR (Status)) {
722     goto ErrorExit;
723   }
724 
725   Status = PciIo->Attributes (
726                     PciIo,
727                     EfiPciIoAttributeOperationSupported,
728                     0,
729                     &EnabledPciAttributes
730                     );
731   if (!EFI_ERROR (Status)) {
732     EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
733     Status = PciIo->Attributes (
734                       PciIo,
735                       EfiPciIoAttributeOperationEnable,
736                       EnabledPciAttributes,
737                       NULL
738                       );
739   }
740 
741   if (EFI_ERROR (Status)) {
742     goto ErrorExit;
743   }
744 
745   Status = gBS->LocateProtocol (&gEdkiiAtaAtapiPolicyProtocolGuid, NULL, (VOID **)&mAtaAtapiPolicy);
746   if (EFI_ERROR (Status)) {
747     //
748     // If there is no AtaAtapiPolicy exposed, use the default policy.
749     //
750     mAtaAtapiPolicy = &mDefaultAtaAtapiPolicy;
751   }
752 
753   //
754   // Allocate a buffer to store the ATA_ATAPI_PASS_THRU_INSTANCE data structure
755   //
756   Instance = AllocateCopyPool (sizeof (ATA_ATAPI_PASS_THRU_INSTANCE), &gAtaAtapiPassThruInstanceTemplate);
757   if (Instance == NULL) {
758     goto ErrorExit;
759   }
760 
761   Instance->ControllerHandle      = Controller;
762   Instance->IdeControllerInit     = IdeControllerInit;
763   Instance->PciIo                 = PciIo;
764   Instance->EnabledPciAttributes  = EnabledPciAttributes;
765   Instance->OriginalPciAttributes = OriginalPciAttributes;
766   Instance->AtaPassThru.Mode      = &Instance->AtaPassThruMode;
767   Instance->ExtScsiPassThru.Mode  = &Instance->ExtScsiPassThruMode;
768   InitializeListHead(&Instance->DeviceList);
769   InitializeListHead(&Instance->NonBlockingTaskList);
770 
771   Instance->TimerEvent = NULL;
772 
773   Status = gBS->CreateEvent (
774                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
775                   TPL_NOTIFY,
776                   AsyncNonBlockingTransferRoutine,
777                   Instance,
778                   &Instance->TimerEvent
779                   );
780   if (EFI_ERROR (Status)) {
781     goto ErrorExit;
782   }
783 
784   //
785   // Set 1ms timer.
786   //
787   Status = gBS->SetTimer (Instance->TimerEvent, TimerPeriodic, 10000);
788   if (EFI_ERROR (Status)) {
789     goto ErrorExit;
790   }
791 
792   //
793   // Enumerate all inserted ATA devices.
794   //
795   Status = EnumerateAttachedDevice (Instance);
796   if (EFI_ERROR (Status)) {
797     goto ErrorExit;
798   }
799 
800   Status = gBS->InstallMultipleProtocolInterfaces (
801                   &Controller,
802                   &gEfiAtaPassThruProtocolGuid, &(Instance->AtaPassThru),
803                   &gEfiExtScsiPassThruProtocolGuid, &(Instance->ExtScsiPassThru),
804                   NULL
805                   );
806   ASSERT_EFI_ERROR (Status);
807 
808   return Status;
809 
810 ErrorExit:
811   if (IdeControllerInit != NULL) {
812     gBS->CloseProtocol (
813            Controller,
814            &gEfiIdeControllerInitProtocolGuid,
815            This->DriverBindingHandle,
816            Controller
817            );
818   }
819 
820   if ((Instance != NULL) && (Instance->TimerEvent != NULL)) {
821     gBS->CloseEvent (Instance->TimerEvent);
822   }
823 
824   if (Instance != NULL) {
825     //
826     // Remove all inserted ATA devices.
827     //
828     DestroyDeviceInfoList (Instance);
829     FreePool (Instance);
830   }
831   return EFI_UNSUPPORTED;
832 }
833 
834 /**
835   Stops a device controller or a bus controller.
836 
837   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
838   As a result, much of the error checking on the parameters to Stop() has been moved
839   into this common boot service. It is legal to call Stop() from other locations,
840   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
841   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
842      same driver's Start() function.
843   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
844      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
845      Start() function, and the Start() function must have called OpenProtocol() on
846      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
847 
848   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
849   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
850                                 support a bus specific I/O protocol for the driver
851                                 to use to stop the device.
852   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
853   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
854                                 if NumberOfChildren is 0.
855 
856   @retval EFI_SUCCESS           The device was stopped.
857   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
858 
859 **/
860 EFI_STATUS
861 EFIAPI
AtaAtapiPassThruStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)862 AtaAtapiPassThruStop (
863   IN  EFI_DRIVER_BINDING_PROTOCOL       *This,
864   IN  EFI_HANDLE                        Controller,
865   IN  UINTN                             NumberOfChildren,
866   IN  EFI_HANDLE                        *ChildHandleBuffer
867   )
868 {
869   EFI_STATUS                        Status;
870   ATA_ATAPI_PASS_THRU_INSTANCE      *Instance;
871   EFI_ATA_PASS_THRU_PROTOCOL        *AtaPassThru;
872   EFI_PCI_IO_PROTOCOL               *PciIo;
873   EFI_AHCI_REGISTERS                *AhciRegisters;
874 
875   DEBUG ((EFI_D_INFO, "==AtaAtapiPassThru Stop== Controller = %x\n", Controller));
876 
877   Status = gBS->OpenProtocol (
878                   Controller,
879                   &gEfiAtaPassThruProtocolGuid,
880                   (VOID **) &AtaPassThru,
881                   This->DriverBindingHandle,
882                   Controller,
883                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
884                   );
885 
886   if (EFI_ERROR (Status)) {
887     return EFI_DEVICE_ERROR;
888   }
889 
890   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (AtaPassThru);
891 
892   Status = gBS->UninstallMultipleProtocolInterfaces (
893                   Controller,
894                   &gEfiAtaPassThruProtocolGuid, &(Instance->AtaPassThru),
895                   &gEfiExtScsiPassThruProtocolGuid, &(Instance->ExtScsiPassThru),
896                   NULL
897                   );
898 
899   if (EFI_ERROR (Status)) {
900     return EFI_DEVICE_ERROR;
901   }
902 
903   //
904   // Close protocols opened by AtaAtapiPassThru controller driver
905   //
906   gBS->CloseProtocol (
907          Controller,
908          &gEfiIdeControllerInitProtocolGuid,
909          This->DriverBindingHandle,
910          Controller
911          );
912 
913   //
914   // Close Non-Blocking timer and free Task list.
915   //
916   if (Instance->TimerEvent != NULL) {
917     gBS->CloseEvent (Instance->TimerEvent);
918     Instance->TimerEvent = NULL;
919   }
920   DestroyAsynTaskList (Instance, FALSE);
921   //
922   // Free allocated resource
923   //
924   DestroyDeviceInfoList (Instance);
925 
926   PciIo = Instance->PciIo;
927 
928   //
929   // Disable this ATA host controller.
930   //
931   PciIo->Attributes (
932            PciIo,
933            EfiPciIoAttributeOperationDisable,
934            Instance->EnabledPciAttributes,
935            NULL
936            );
937 
938   //
939   // If the current working mode is AHCI mode, then pre-allocated resource
940   // for AHCI initialization should be released.
941   //
942   if (Instance->Mode == EfiAtaAhciMode) {
943     AhciRegisters = &Instance->AhciRegisters;
944     PciIo->Unmap (
945              PciIo,
946              AhciRegisters->MapCommandTable
947              );
948     PciIo->FreeBuffer (
949              PciIo,
950              EFI_SIZE_TO_PAGES ((UINTN) AhciRegisters->MaxCommandTableSize),
951              AhciRegisters->AhciCommandTable
952              );
953     PciIo->Unmap (
954              PciIo,
955              AhciRegisters->MapCmdList
956              );
957     PciIo->FreeBuffer (
958              PciIo,
959              EFI_SIZE_TO_PAGES ((UINTN) AhciRegisters->MaxCommandListSize),
960              AhciRegisters->AhciCmdList
961              );
962     PciIo->Unmap (
963              PciIo,
964              AhciRegisters->MapRFis
965              );
966     PciIo->FreeBuffer (
967              PciIo,
968              EFI_SIZE_TO_PAGES ((UINTN) AhciRegisters->MaxReceiveFisSize),
969              AhciRegisters->AhciRFis
970              );
971   }
972 
973   //
974   // Restore original PCI attributes
975   //
976   Status = PciIo->Attributes (
977                     PciIo,
978                     EfiPciIoAttributeOperationSet,
979                     Instance->OriginalPciAttributes,
980                     NULL
981                     );
982   ASSERT_EFI_ERROR (Status);
983 
984   FreePool (Instance);
985 
986   return Status;
987 }
988 
989 /**
990   Traverse the attached ATA devices list to find out the device to access.
991 
992   @param[in]  Instance            A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
993   @param[in]  Port                The port number of the ATA device to send the command.
994   @param[in]  PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
995                                   If there is no port multiplier, then specify 0xFFFF.
996   @param[in]  DeviceType          The device type of the ATA device.
997 
998   @retval     The pointer to the data structure of the device info to access.
999 
1000 **/
1001 LIST_ENTRY *
1002 EFIAPI
SearchDeviceInfoList(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance,IN UINT16 Port,IN UINT16 PortMultiplier,IN EFI_ATA_DEVICE_TYPE DeviceType)1003 SearchDeviceInfoList (
1004   IN  ATA_ATAPI_PASS_THRU_INSTANCE  *Instance,
1005   IN  UINT16                         Port,
1006   IN  UINT16                         PortMultiplier,
1007   IN  EFI_ATA_DEVICE_TYPE            DeviceType
1008   )
1009 {
1010   EFI_ATA_DEVICE_INFO  *DeviceInfo;
1011   LIST_ENTRY           *Node;
1012 
1013   Node = GetFirstNode (&Instance->DeviceList);
1014   while (!IsNull (&Instance->DeviceList, Node)) {
1015     DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1016 
1017     //
1018     // For CD-ROM working in the AHCI mode, only 8 bits are used to record
1019     // the PortMultiplier information. If the CD-ROM is directly attached
1020     // on a SATA port, the PortMultiplier should be translated from 0xFF
1021     // to 0xFFFF according to the UEFI spec.
1022     //
1023     if ((Instance->Mode == EfiAtaAhciMode) &&
1024         (DeviceInfo->Type == EfiIdeCdrom) &&
1025         (PortMultiplier == 0xFF)) {
1026         PortMultiplier = 0xFFFF;
1027     }
1028 
1029     if ((DeviceInfo->Type == DeviceType) &&
1030         (Port == DeviceInfo->Port) &&
1031         (PortMultiplier == DeviceInfo->PortMultiplier)) {
1032       return Node;
1033     }
1034 
1035     Node = GetNextNode (&Instance->DeviceList, Node);
1036   }
1037 
1038   return NULL;
1039 }
1040 
1041 /**
1042   Allocate device info data structure to contain device info.
1043   And insert the data structure to the tail of device list for tracing.
1044 
1045   @param[in]  Instance            A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1046   @param[in]  Port                The port number of the ATA device to send the command.
1047   @param[in]  PortMultiplierPort  The port multiplier port number of the ATA device to send the command.
1048                                   If there is no port multiplier, then specify 0xFFFF.
1049   @param[in]  DeviceType          The device type of the ATA device.
1050   @param[in]  IdentifyData        The data buffer to store the output of the IDENTIFY cmd.
1051 
1052   @retval EFI_SUCCESS             Successfully insert the ata device to the tail of device list.
1053   @retval EFI_OUT_OF_RESOURCES    Can not allocate enough resource for use.
1054 
1055 **/
1056 EFI_STATUS
1057 EFIAPI
CreateNewDeviceInfo(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance,IN UINT16 Port,IN UINT16 PortMultiplier,IN EFI_ATA_DEVICE_TYPE DeviceType,IN EFI_IDENTIFY_DATA * IdentifyData)1058 CreateNewDeviceInfo (
1059   IN  ATA_ATAPI_PASS_THRU_INSTANCE   *Instance,
1060   IN  UINT16                         Port,
1061   IN  UINT16                         PortMultiplier,
1062   IN  EFI_ATA_DEVICE_TYPE            DeviceType,
1063   IN  EFI_IDENTIFY_DATA              *IdentifyData
1064   )
1065 {
1066   EFI_ATA_DEVICE_INFO  *DeviceInfo;
1067 
1068   DeviceInfo = AllocateZeroPool (sizeof (EFI_ATA_DEVICE_INFO));
1069 
1070   if (DeviceInfo == NULL) {
1071     return EFI_OUT_OF_RESOURCES;
1072   }
1073 
1074   DeviceInfo->Signature      = ATA_ATAPI_DEVICE_SIGNATURE;
1075   DeviceInfo->Port           = Port;
1076   DeviceInfo->PortMultiplier = PortMultiplier;
1077   DeviceInfo->Type           = DeviceType;
1078 
1079   if (IdentifyData != NULL) {
1080     DeviceInfo->IdentifyData = AllocateCopyPool (sizeof (EFI_IDENTIFY_DATA), IdentifyData);
1081     if (DeviceInfo->IdentifyData == NULL) {
1082       FreePool (DeviceInfo);
1083       return EFI_OUT_OF_RESOURCES;
1084     }
1085   }
1086 
1087   InsertTailList (&Instance->DeviceList, &DeviceInfo->Link);
1088 
1089   return EFI_SUCCESS;
1090 }
1091 
1092 /**
1093   Destroy all attached ATA devices info.
1094 
1095   @param[in]  Instance          A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1096 
1097 **/
1098 VOID
1099 EFIAPI
DestroyDeviceInfoList(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance)1100 DestroyDeviceInfoList (
1101   IN  ATA_ATAPI_PASS_THRU_INSTANCE  *Instance
1102   )
1103 {
1104   EFI_ATA_DEVICE_INFO  *DeviceInfo;
1105   LIST_ENTRY           *Node;
1106 
1107   Node = GetFirstNode (&Instance->DeviceList);
1108   while (!IsNull (&Instance->DeviceList, Node)) {
1109     DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1110 
1111     Node = GetNextNode (&Instance->DeviceList, Node);
1112 
1113     RemoveEntryList (&DeviceInfo->Link);
1114     if (DeviceInfo->IdentifyData != NULL) {
1115       FreePool (DeviceInfo->IdentifyData);
1116     }
1117     FreePool (DeviceInfo);
1118   }
1119 }
1120 
1121 /**
1122   Destroy all pending non blocking tasks.
1123 
1124   @param[in]  Instance    A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1125   @param[in]  IsSigEvent  Indicate whether signal the task event when remove the
1126                           task.
1127 
1128 **/
1129 VOID
1130 EFIAPI
DestroyAsynTaskList(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance,IN BOOLEAN IsSigEvent)1131 DestroyAsynTaskList (
1132   IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
1133   IN BOOLEAN                       IsSigEvent
1134   )
1135 {
1136   LIST_ENTRY           *Entry;
1137   LIST_ENTRY           *DelEntry;
1138   ATA_NONBLOCK_TASK    *Task;
1139   EFI_TPL              OldTpl;
1140 
1141   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1142   if (!IsListEmpty (&Instance->NonBlockingTaskList)) {
1143     //
1144     // Free the Subtask list.
1145     //
1146     for (Entry = (&Instance->NonBlockingTaskList)->ForwardLink;
1147         Entry != (&Instance->NonBlockingTaskList);
1148        ) {
1149       DelEntry = Entry;
1150       Entry    = Entry->ForwardLink;
1151       Task     = ATA_NON_BLOCK_TASK_FROM_ENTRY (DelEntry);
1152 
1153       RemoveEntryList (DelEntry);
1154       if (IsSigEvent) {
1155         Task->Packet->Asb->AtaStatus = 0x01;
1156         gBS->SignalEvent (Task->Event);
1157       }
1158       FreePool (Task);
1159     }
1160   }
1161   gBS->RestoreTPL (OldTpl);
1162 }
1163 
1164 /**
1165   Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
1166 
1167   The function is designed to enumerate all attached ATA devices.
1168 
1169   @param[in]  Instance          A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1170 
1171   @retval EFI_SUCCESS           Successfully enumerate attached ATA devices.
1172   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
1173 
1174 **/
1175 EFI_STATUS
1176 EFIAPI
EnumerateAttachedDevice(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance)1177 EnumerateAttachedDevice (
1178   IN  ATA_ATAPI_PASS_THRU_INSTANCE      *Instance
1179   )
1180 {
1181   EFI_STATUS                   Status;
1182   PCI_TYPE00                   PciData;
1183   UINT8                        ClassCode;
1184 
1185   Status = EFI_SUCCESS;
1186 
1187   Status = Instance->PciIo->Pci.Read (
1188                                   Instance->PciIo,
1189                                   EfiPciIoWidthUint8,
1190                                   PCI_CLASSCODE_OFFSET,
1191                                   sizeof (PciData.Hdr.ClassCode),
1192                                   PciData.Hdr.ClassCode
1193                                   );
1194   ASSERT_EFI_ERROR (Status);
1195 
1196   ClassCode = PciData.Hdr.ClassCode[1];
1197 
1198   switch (ClassCode) {
1199     case PCI_CLASS_MASS_STORAGE_IDE :
1200       //
1201       // The ATA controller is working at IDE mode
1202       //
1203       Instance->Mode = EfiAtaIdeMode;
1204 
1205       Status = IdeModeInitialization (Instance);
1206       if (EFI_ERROR (Status)) {
1207         Status = EFI_DEVICE_ERROR;
1208         goto Done;
1209       }
1210       break;
1211     case PCI_CLASS_MASS_STORAGE_SATADPA :
1212       //
1213       // The ATA controller is working at AHCI mode
1214       //
1215       Instance->Mode = EfiAtaAhciMode;
1216 
1217       Status = AhciModeInitialization (Instance);
1218 
1219       if (EFI_ERROR (Status)) {
1220         Status = EFI_DEVICE_ERROR;
1221         goto Done;
1222       }
1223 
1224       break;
1225     default :
1226       Status = EFI_UNSUPPORTED;
1227   }
1228 
1229 Done:
1230   return Status;
1231 }
1232 
1233 /**
1234   Sends an ATA command to an ATA device that is attached to the ATA controller. This function
1235   supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
1236   and the non-blocking I/O functionality is optional.
1237 
1238   @param[in]      This               A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1239   @param[in]      Port               The port number of the ATA device to send the command.
1240   @param[in]      PortMultiplierPort The port multiplier port number of the ATA device to send the command.
1241                                      If there is no port multiplier, then specify 0xFFFF.
1242   @param[in, out] Packet             A pointer to the ATA command to send to the ATA device specified by Port
1243                                      and PortMultiplierPort.
1244   @param[in]      Event               If non-blocking I/O is not supported then Event is ignored, and blocking
1245                                      I/O is performed. If Event is NULL, then blocking I/O is performed. If
1246                                      Event is not NULL and non blocking I/O is supported, then non-blocking
1247                                      I/O is performed, and Event will be signaled when the ATA command completes.
1248 
1249   @retval EFI_SUCCESS                The ATA command was sent by the host. For bi-directional commands,
1250                                      InTransferLength bytes were transferred from InDataBuffer. For write and
1251                                      bi-directional commands, OutTransferLength bytes were transferred by OutDataBuffer.
1252   @retval EFI_BAD_BUFFER_SIZE        The ATA command was not executed. The number of bytes that could be transferred
1253                                      is returned in InTransferLength. For write and bi-directional commands,
1254                                      OutTransferLength bytes were transferred by OutDataBuffer.
1255   @retval EFI_NOT_READY              The ATA command could not be sent because there are too many ATA commands
1256                                      already queued. The caller may retry again later.
1257   @retval EFI_DEVICE_ERROR           A device error occurred while attempting to send the ATA command.
1258   @retval EFI_INVALID_PARAMETER      Port, PortMultiplierPort, or the contents of Acb are invalid. The ATA
1259                                      command was not sent, so no additional status information is available.
1260 
1261 **/
1262 EFI_STATUS
1263 EFIAPI
AtaPassThruPassThru(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN UINT16 Port,IN UINT16 PortMultiplierPort,IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET * Packet,IN EFI_EVENT Event OPTIONAL)1264 AtaPassThruPassThru (
1265   IN     EFI_ATA_PASS_THRU_PROTOCOL       *This,
1266   IN     UINT16                           Port,
1267   IN     UINT16                           PortMultiplierPort,
1268   IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
1269   IN     EFI_EVENT                        Event OPTIONAL
1270   )
1271 {
1272   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1273   LIST_ENTRY                      *Node;
1274   EFI_ATA_DEVICE_INFO             *DeviceInfo;
1275   EFI_IDENTIFY_DATA               *IdentifyData;
1276   UINT64                          Capacity;
1277   UINT32                          MaxSectorCount;
1278   ATA_NONBLOCK_TASK               *Task;
1279   EFI_TPL                         OldTpl;
1280   UINT32                          BlockSize;
1281 
1282   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1283 
1284   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {
1285     return EFI_INVALID_PARAMETER;
1286   }
1287 
1288   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->OutDataBuffer, This->Mode->IoAlign)) {
1289     return EFI_INVALID_PARAMETER;
1290   }
1291 
1292   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->Asb, This->Mode->IoAlign)) {
1293     return EFI_INVALID_PARAMETER;
1294   }
1295 
1296   Node = SearchDeviceInfoList (Instance, Port, PortMultiplierPort, EfiIdeHarddisk);
1297 
1298   if (Node == NULL) {
1299     Node = SearchDeviceInfoList(Instance, Port, PortMultiplierPort, EfiIdeCdrom);
1300     if (Node == NULL) {
1301       return EFI_INVALID_PARAMETER;
1302     }
1303   }
1304 
1305   //
1306   // Check whether this device needs 48-bit addressing (ATAPI-6 ata device).
1307   // Per ATA-6 spec, word83: bit15 is zero and bit14 is one.
1308   // If bit10 is one, it means the ata device support 48-bit addressing.
1309   //
1310   DeviceInfo     = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1311   IdentifyData   = DeviceInfo->IdentifyData;
1312   MaxSectorCount = 0x100;
1313   if ((IdentifyData->AtaData.command_set_supported_83 & (BIT10 | BIT15 | BIT14)) == 0x4400) {
1314     Capacity = *((UINT64 *)IdentifyData->AtaData.maximum_lba_for_48bit_addressing);
1315     if (Capacity > 0xFFFFFFF) {
1316       //
1317       // Capacity exceeds 120GB. 48-bit addressing is really needed
1318       // In this case, the max sector count is 0x10000
1319       //
1320       MaxSectorCount = 0x10000;
1321     }
1322   }
1323 
1324   BlockSize = 0x200;
1325   if ((IdentifyData->AtaData.phy_logic_sector_support & (BIT14 | BIT15)) == BIT14) {
1326     //
1327     // Check logical block size
1328     //
1329     if ((IdentifyData->AtaData.phy_logic_sector_support & BIT12) != 0) {
1330       BlockSize = (UINT32) (((IdentifyData->AtaData.logic_sector_size_hi << 16) | IdentifyData->AtaData.logic_sector_size_lo) * sizeof (UINT16));
1331     }
1332   }
1333 
1334   //
1335   // convert the transfer length from sector count to byte.
1336   //
1337   if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
1338        (Packet->InTransferLength != 0)) {
1339     Packet->InTransferLength = Packet->InTransferLength * BlockSize;
1340   }
1341 
1342   //
1343   // convert the transfer length from sector count to byte.
1344   //
1345   if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
1346        (Packet->OutTransferLength != 0)) {
1347     Packet->OutTransferLength = Packet->OutTransferLength * BlockSize;
1348   }
1349 
1350   //
1351   // If the data buffer described by InDataBuffer/OutDataBuffer and InTransferLength/OutTransferLength
1352   // is too big to be transferred in a single command, then no data is transferred and EFI_BAD_BUFFER_SIZE
1353   // is returned.
1354   //
1355   if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * BlockSize)) ||
1356       ((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * BlockSize))) {
1357     return EFI_BAD_BUFFER_SIZE;
1358   }
1359 
1360   //
1361   // For non-blocking mode, queue the Task into the list.
1362   //
1363   if (Event != NULL) {
1364     Task = AllocateZeroPool (sizeof (ATA_NONBLOCK_TASK));
1365     if (Task == NULL) {
1366       return EFI_OUT_OF_RESOURCES;
1367     }
1368 
1369     Task->Signature      = ATA_NONBLOCKING_TASK_SIGNATURE;
1370     Task->Port           = Port;
1371     Task->PortMultiplier = PortMultiplierPort;
1372     Task->Packet         = Packet;
1373     Task->Event          = Event;
1374     Task->IsStart        = FALSE;
1375     Task->RetryTimes     = DivU64x32(Packet->Timeout, 1000) + 1;
1376     if (Packet->Timeout == 0) {
1377       Task->InfiniteWait = TRUE;
1378     } else {
1379       Task->InfiniteWait = FALSE;
1380     }
1381 
1382     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1383     InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);
1384     gBS->RestoreTPL (OldTpl);
1385 
1386     return EFI_SUCCESS;
1387   } else {
1388     return AtaPassThruPassThruExecute (
1389              Port,
1390              PortMultiplierPort,
1391              Packet,
1392              Instance,
1393              NULL
1394              );
1395   }
1396 }
1397 
1398 /**
1399   Used to retrieve the list of legal port numbers for ATA devices on an ATA controller.
1400   These can either be the list of ports where ATA devices are actually present or the
1401   list of legal port numbers for the ATA controller. Regardless, the caller of this
1402   function must probe the port number returned to see if an ATA device is actually
1403   present at that location on the ATA controller.
1404 
1405   The GetNextPort() function retrieves the port number on an ATA controller. If on input
1406   Port is 0xFFFF, then the port number of the first port on the ATA controller is returned
1407   in Port and EFI_SUCCESS is returned.
1408 
1409   If Port is a port number that was returned on a previous call to GetNextPort(), then the
1410   port number of the next port on the ATA controller is returned in Port, and EFI_SUCCESS
1411   is returned. If Port is not 0xFFFF and Port was not returned on a previous call to
1412   GetNextPort(), then EFI_INVALID_PARAMETER is returned.
1413 
1414   If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND is
1415   returned.
1416 
1417   @param[in]      This          A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1418   @param[in, out] Port          On input, a pointer to the port number on the ATA controller.
1419                                 On output, a pointer to the next port number on the ATA
1420                                 controller. An input value of 0xFFFF retrieves the first port
1421                                 number on the ATA controller.
1422 
1423   @retval EFI_SUCCESS           The next port number on the ATA controller was returned in Port.
1424   @retval EFI_NOT_FOUND         There are no more ports on this ATA controller.
1425   @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned on a previous call
1426                                 to GetNextPort().
1427 
1428 **/
1429 EFI_STATUS
1430 EFIAPI
AtaPassThruGetNextPort(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN OUT UINT16 * Port)1431 AtaPassThruGetNextPort (
1432   IN EFI_ATA_PASS_THRU_PROTOCOL *This,
1433   IN OUT UINT16                 *Port
1434   )
1435 {
1436   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1437   LIST_ENTRY                      *Node;
1438   EFI_ATA_DEVICE_INFO             *DeviceInfo;
1439 
1440   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1441 
1442   if (Port == NULL) {
1443     return EFI_INVALID_PARAMETER;
1444   }
1445 
1446   if (*Port == 0xFFFF) {
1447     //
1448     // If the Port is all 0xFF's, start to traverse the device list from the beginning
1449     //
1450     Node = GetFirstNode (&Instance->DeviceList);
1451 
1452     while (!IsNull (&Instance->DeviceList, Node)) {
1453       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1454 
1455       if (DeviceInfo->Type == EfiIdeHarddisk) {
1456         *Port = DeviceInfo->Port;
1457         goto Exit;
1458       }
1459 
1460       Node = GetNextNode (&Instance->DeviceList, Node);
1461     }
1462 
1463     return EFI_NOT_FOUND;
1464   } else if (*Port == Instance->PreviousPort) {
1465     Node = GetFirstNode (&Instance->DeviceList);
1466 
1467     while (!IsNull (&Instance->DeviceList, Node)) {
1468       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1469 
1470       if ((DeviceInfo->Type == EfiIdeHarddisk) &&
1471            (DeviceInfo->Port > *Port)){
1472         *Port = DeviceInfo->Port;
1473         goto Exit;
1474       }
1475 
1476       Node = GetNextNode (&Instance->DeviceList, Node);
1477     }
1478 
1479     return EFI_NOT_FOUND;
1480   } else {
1481     //
1482     // Port is not equal to 0xFFFF and also not equal to previous return value
1483     //
1484     return EFI_INVALID_PARAMETER;
1485   }
1486 
1487 Exit:
1488   //
1489   // Update the PreviousPort and PreviousPortMultiplier.
1490   //
1491   Instance->PreviousPort = *Port;
1492 
1493   return EFI_SUCCESS;
1494 }
1495 
1496 /**
1497   Used to retrieve the list of legal port multiplier port numbers for ATA devices on a port of an ATA
1498   controller. These can either be the list of port multiplier ports where ATA devices are actually
1499   present on port or the list of legal port multiplier ports on that port. Regardless, the caller of this
1500   function must probe the port number and port multiplier port number returned to see if an ATA
1501   device is actually present.
1502 
1503   The GetNextDevice() function retrieves the port multiplier port number of an ATA device
1504   present on a port of an ATA controller.
1505 
1506   If PortMultiplierPort points to a port multiplier port number value that was returned on a
1507   previous call to GetNextDevice(), then the port multiplier port number of the next ATA device
1508   on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is
1509   returned.
1510 
1511   If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first
1512   ATA device on port of the ATA controller is returned in PortMultiplierPort and
1513   EFI_SUCCESS is returned.
1514 
1515   If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort
1516   was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER
1517   is returned.
1518 
1519   If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of
1520   the ATA controller, then EFI_NOT_FOUND is returned.
1521 
1522   @param[in]      This               A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1523   @param[in]      Port               The port number present on the ATA controller.
1524   @param[in, out] PortMultiplierPort On input, a pointer to the port multiplier port number of an
1525                                      ATA device present on the ATA controller.
1526                                      If on input a PortMultiplierPort of 0xFFFF is specified,
1527                                      then the port multiplier port number of the first ATA device
1528                                      is returned. On output, a pointer to the port multiplier port
1529                                      number of the next ATA device present on an ATA controller.
1530 
1531   @retval EFI_SUCCESS                The port multiplier port number of the next ATA device on the port
1532                                      of the ATA controller was returned in PortMultiplierPort.
1533   @retval EFI_NOT_FOUND              There are no more ATA devices on this port of the ATA controller.
1534   @retval EFI_INVALID_PARAMETER      PortMultiplierPort is not 0xFFFF, and PortMultiplierPort was not
1535                                      returned on a previous call to GetNextDevice().
1536 
1537 **/
1538 EFI_STATUS
1539 EFIAPI
AtaPassThruGetNextDevice(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN UINT16 Port,IN OUT UINT16 * PortMultiplierPort)1540 AtaPassThruGetNextDevice (
1541   IN EFI_ATA_PASS_THRU_PROTOCOL *This,
1542   IN UINT16                     Port,
1543   IN OUT UINT16                 *PortMultiplierPort
1544   )
1545 {
1546   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1547   LIST_ENTRY                      *Node;
1548   EFI_ATA_DEVICE_INFO             *DeviceInfo;
1549 
1550   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1551 
1552   if (PortMultiplierPort == NULL) {
1553     return EFI_INVALID_PARAMETER;
1554   }
1555 
1556   if (Instance->PreviousPortMultiplier == 0xFFFF) {
1557     //
1558     // If a device is directly attached on a port, previous call to this
1559     // function will return the value 0xFFFF for PortMultiplierPort. In
1560     // this case, there should be no more device on the port multiplier.
1561     //
1562     Instance->PreviousPortMultiplier = 0;
1563     return EFI_NOT_FOUND;
1564   }
1565 
1566   if (*PortMultiplierPort == Instance->PreviousPortMultiplier) {
1567     Node = GetFirstNode (&Instance->DeviceList);
1568 
1569     while (!IsNull (&Instance->DeviceList, Node)) {
1570       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1571 
1572       if ((DeviceInfo->Type == EfiIdeHarddisk) &&
1573            (DeviceInfo->Port == Port) &&
1574            (DeviceInfo->PortMultiplier > *PortMultiplierPort)){
1575         *PortMultiplierPort = DeviceInfo->PortMultiplier;
1576         goto Exit;
1577       }
1578 
1579       Node = GetNextNode (&Instance->DeviceList, Node);
1580     }
1581 
1582     return EFI_NOT_FOUND;
1583   } else if (*PortMultiplierPort == 0xFFFF) {
1584     //
1585     // If the PortMultiplierPort is all 0xFF's, start to traverse the device list from the beginning
1586     //
1587     Node = GetFirstNode (&Instance->DeviceList);
1588 
1589     while (!IsNull (&Instance->DeviceList, Node)) {
1590       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
1591 
1592       if ((DeviceInfo->Type == EfiIdeHarddisk) &&
1593            (DeviceInfo->Port == Port)){
1594         *PortMultiplierPort = DeviceInfo->PortMultiplier;
1595         goto Exit;
1596       }
1597 
1598       Node = GetNextNode (&Instance->DeviceList, Node);
1599     }
1600 
1601     return EFI_NOT_FOUND;
1602   } else {
1603     //
1604     // PortMultiplierPort is not equal to 0xFFFF and also not equal to previous return value
1605     //
1606     return EFI_INVALID_PARAMETER;
1607   }
1608 
1609 Exit:
1610   //
1611   // Update the PreviousPort and PreviousPortMultiplier.
1612   //
1613   Instance->PreviousPortMultiplier = *PortMultiplierPort;
1614 
1615   return EFI_SUCCESS;
1616 }
1617 
1618 /**
1619   Used to allocate and build a device path node for an ATA device on an ATA controller.
1620 
1621   The BuildDevicePath() function allocates and builds a single device node for the ATA
1622   device specified by Port and PortMultiplierPort. If the ATA device specified by Port and
1623   PortMultiplierPort is not present on the ATA controller, then EFI_NOT_FOUND is returned.
1624   If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. If there are not enough
1625   resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
1626 
1627   Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of
1628   DevicePath are initialized to describe the ATA device specified by Port and PortMultiplierPort,
1629   and EFI_SUCCESS is returned.
1630 
1631   @param[in]      This               A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1632   @param[in]      Port               Port specifies the port number of the ATA device for which a
1633                                      device path node is to be allocated and built.
1634   @param[in]      PortMultiplierPort The port multiplier port number of the ATA device for which a
1635                                      device path node is to be allocated and built. If there is no
1636                                      port multiplier, then specify 0xFFFF.
1637   @param[in, out] DevicePath         A pointer to a single device path node that describes the ATA
1638                                      device specified by Port and PortMultiplierPort. This function
1639                                      is responsible for allocating the buffer DevicePath with the
1640                                      boot service AllocatePool(). It is the caller's responsibility
1641                                      to free DevicePath when the caller is finished with DevicePath.
1642   @retval EFI_SUCCESS                The device path node that describes the ATA device specified by
1643                                      Port and PortMultiplierPort was allocated and returned in DevicePath.
1644   @retval EFI_NOT_FOUND              The ATA device specified by Port and PortMultiplierPort does not
1645                                      exist on the ATA controller.
1646   @retval EFI_INVALID_PARAMETER      DevicePath is NULL.
1647   @retval EFI_OUT_OF_RESOURCES       There are not enough resources to allocate DevicePath.
1648 
1649 **/
1650 EFI_STATUS
1651 EFIAPI
AtaPassThruBuildDevicePath(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN UINT16 Port,IN UINT16 PortMultiplierPort,IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath)1652 AtaPassThruBuildDevicePath (
1653   IN     EFI_ATA_PASS_THRU_PROTOCOL *This,
1654   IN     UINT16                     Port,
1655   IN     UINT16                     PortMultiplierPort,
1656   IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath
1657   )
1658 {
1659   EFI_DEV_PATH                    *DevicePathNode;
1660   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1661   LIST_ENTRY                      *Node;
1662 
1663   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1664 
1665   //
1666   // Validate parameters passed in.
1667   //
1668   if (DevicePath == NULL) {
1669     return EFI_INVALID_PARAMETER;
1670   }
1671 
1672   Node = SearchDeviceInfoList(Instance, Port, PortMultiplierPort, EfiIdeHarddisk);
1673   if (Node == NULL) {
1674     return EFI_NOT_FOUND;
1675   }
1676 
1677   if (Instance->Mode == EfiAtaIdeMode) {
1678     DevicePathNode = AllocateCopyPool (sizeof (ATAPI_DEVICE_PATH), &mAtapiDevicePathTemplate);
1679     if (DevicePathNode == NULL) {
1680       return EFI_OUT_OF_RESOURCES;
1681     }
1682     DevicePathNode->Atapi.PrimarySecondary = (UINT8) Port;
1683     DevicePathNode->Atapi.SlaveMaster      = (UINT8) PortMultiplierPort;
1684     DevicePathNode->Atapi.Lun              = 0;
1685   } else {
1686     DevicePathNode = AllocateCopyPool (sizeof (SATA_DEVICE_PATH), &mSataDevicePathTemplate);
1687     if (DevicePathNode == NULL) {
1688       return EFI_OUT_OF_RESOURCES;
1689     }
1690 
1691     DevicePathNode->Sata.HBAPortNumber            = Port;
1692     DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplierPort;
1693     DevicePathNode->Sata.Lun                      = 0;
1694   }
1695 
1696   *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathNode;
1697 
1698   return EFI_SUCCESS;
1699 }
1700 
1701 /**
1702   Used to translate a device path node to a port number and port multiplier port number.
1703 
1704   The GetDevice() function determines the port and port multiplier port number associated with
1705   the ATA device described by DevicePath. If DevicePath is a device path node type that the
1706   ATA Pass Thru driver supports, then the ATA Pass Thru driver will attempt to translate the contents
1707   DevicePath into a port number and port multiplier port number.
1708 
1709   If this translation is successful, then that port number and port multiplier port number are returned
1710   in Port and PortMultiplierPort, and EFI_SUCCESS is returned.
1711 
1712   If DevicePath, Port, or PortMultiplierPort are NULL, then EFI_INVALID_PARAMETER is returned.
1713 
1714   If DevicePath is not a device path node type that the ATA Pass Thru driver supports, then
1715   EFI_UNSUPPORTED is returned.
1716 
1717   If DevicePath is a device path node type that the ATA Pass Thru driver supports, but there is not
1718   a valid translation from DevicePath to a port number and port multiplier port number, then
1719   EFI_NOT_FOUND is returned.
1720 
1721   @param[in]  This                A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1722   @param[in]  DevicePath          A pointer to the device path node that describes an ATA device on the
1723                                   ATA controller.
1724   @param[out] Port                On return, points to the port number of an ATA device on the ATA controller.
1725   @param[out] PortMultiplierPort  On return, points to the port multiplier port number of an ATA device
1726                                   on the ATA controller.
1727 
1728   @retval EFI_SUCCESS             DevicePath was successfully translated to a port number and port multiplier
1729                                   port number, and they were returned in Port and PortMultiplierPort.
1730   @retval EFI_INVALID_PARAMETER   DevicePath is NULL.
1731   @retval EFI_INVALID_PARAMETER   Port is NULL.
1732   @retval EFI_INVALID_PARAMETER   PortMultiplierPort is NULL.
1733   @retval EFI_UNSUPPORTED         This driver does not support the device path node type in DevicePath.
1734   @retval EFI_NOT_FOUND           A valid translation from DevicePath to a port number and port multiplier
1735                                   port number does not exist.
1736 **/
1737 EFI_STATUS
1738 EFIAPI
AtaPassThruGetDevice(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,OUT UINT16 * Port,OUT UINT16 * PortMultiplierPort)1739 AtaPassThruGetDevice (
1740   IN  EFI_ATA_PASS_THRU_PROTOCOL *This,
1741   IN  EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
1742   OUT UINT16                     *Port,
1743   OUT UINT16                     *PortMultiplierPort
1744   )
1745 {
1746   EFI_DEV_PATH                    *DevicePathNode;
1747   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1748   LIST_ENTRY                      *Node;
1749 
1750   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1751 
1752   //
1753   // Validate parameters passed in.
1754   //
1755   if (DevicePath == NULL || Port == NULL || PortMultiplierPort == NULL) {
1756     return EFI_INVALID_PARAMETER;
1757   }
1758 
1759   //
1760   // Check whether the DevicePath belongs to SCSI_DEVICE_PATH or ATAPI_DEVICE_PATH
1761   //
1762   if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
1763       ((DevicePath->SubType != MSG_SATA_DP) &&
1764       (DevicePath->SubType != MSG_ATAPI_DP)) ||
1765       ((DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH)) &&
1766       (DevicePathNodeLength(DevicePath) != sizeof(SATA_DEVICE_PATH)))) {
1767     return EFI_UNSUPPORTED;
1768   }
1769 
1770   DevicePathNode = (EFI_DEV_PATH *) DevicePath;
1771 
1772   if (Instance->Mode == EfiAtaIdeMode) {
1773     *Port               = DevicePathNode->Atapi.PrimarySecondary;
1774     *PortMultiplierPort = DevicePathNode->Atapi.SlaveMaster;
1775   } else {
1776     *Port               = DevicePathNode->Sata.HBAPortNumber;
1777     *PortMultiplierPort = DevicePathNode->Sata.PortMultiplierPortNumber;
1778   }
1779 
1780   Node = SearchDeviceInfoList(Instance, *Port, *PortMultiplierPort, EfiIdeHarddisk);
1781 
1782   if (Node == NULL) {
1783     return EFI_NOT_FOUND;
1784   }
1785 
1786   return EFI_SUCCESS;
1787 }
1788 
1789 /**
1790   Resets a specific port on the ATA controller. This operation also resets all the ATA devices
1791   connected to the port.
1792 
1793   The ResetChannel() function resets an a specific port on an ATA controller. This operation
1794   resets all the ATA devices connected to that port. If this ATA controller does not support
1795   a reset port operation, then EFI_UNSUPPORTED is returned.
1796 
1797   If a device error occurs while executing that port reset operation, then EFI_DEVICE_ERROR is
1798   returned.
1799 
1800   If a timeout occurs during the execution of the port reset operation, then EFI_TIMEOUT is returned.
1801 
1802   If the port reset operation is completed, then EFI_SUCCESS is returned.
1803 
1804   @param[in]  This          A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1805   @param[in]  Port          The port number on the ATA controller.
1806 
1807   @retval EFI_SUCCESS       The ATA controller port was reset.
1808   @retval EFI_UNSUPPORTED   The ATA controller does not support a port reset operation.
1809   @retval EFI_DEVICE_ERROR  A device error occurred while attempting to reset the ATA port.
1810   @retval EFI_TIMEOUT       A timeout occurred while attempting to reset the ATA port.
1811 
1812 **/
1813 EFI_STATUS
1814 EFIAPI
AtaPassThruResetPort(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN UINT16 Port)1815 AtaPassThruResetPort (
1816   IN EFI_ATA_PASS_THRU_PROTOCOL *This,
1817   IN UINT16                     Port
1818   )
1819 {
1820   //
1821   // Return success directly then upper layer driver could think reset port operation is done.
1822   //
1823   return EFI_SUCCESS;
1824 }
1825 
1826 /**
1827   Resets an ATA device that is connected to an ATA controller.
1828 
1829   The ResetDevice() function resets the ATA device specified by Port and PortMultiplierPort.
1830   If this ATA controller does not support a device reset operation, then EFI_UNSUPPORTED is
1831   returned.
1832 
1833   If Port or PortMultiplierPort are not in a valid range for this ATA controller, then
1834   EFI_INVALID_PARAMETER is returned.
1835 
1836   If a device error occurs while executing that device reset operation, then EFI_DEVICE_ERROR
1837   is returned.
1838 
1839   If a timeout occurs during the execution of the device reset operation, then EFI_TIMEOUT is
1840   returned.
1841 
1842   If the device reset operation is completed, then EFI_SUCCESS is returned.
1843 
1844   @param[in] This                A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
1845   @param[in] Port                Port represents the port number of the ATA device to be reset.
1846   @param[in] PortMultiplierPort  The port multiplier port number of the ATA device to reset.
1847                                  If there is no port multiplier, then specify 0xFFFF.
1848   @retval EFI_SUCCESS            The ATA device specified by Port and PortMultiplierPort was reset.
1849   @retval EFI_UNSUPPORTED        The ATA controller does not support a device reset operation.
1850   @retval EFI_INVALID_PARAMETER  Port or PortMultiplierPort are invalid.
1851   @retval EFI_DEVICE_ERROR       A device error occurred while attempting to reset the ATA device
1852                                  specified by Port and PortMultiplierPort.
1853   @retval EFI_TIMEOUT            A timeout occurred while attempting to reset the ATA device
1854                                  specified by Port and PortMultiplierPort.
1855 
1856 **/
1857 EFI_STATUS
1858 EFIAPI
AtaPassThruResetDevice(IN EFI_ATA_PASS_THRU_PROTOCOL * This,IN UINT16 Port,IN UINT16 PortMultiplierPort)1859 AtaPassThruResetDevice (
1860   IN EFI_ATA_PASS_THRU_PROTOCOL *This,
1861   IN UINT16                     Port,
1862   IN UINT16                     PortMultiplierPort
1863   )
1864 {
1865   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1866   LIST_ENTRY                      *Node;
1867 
1868   Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1869 
1870   Node = SearchDeviceInfoList (Instance, Port, PortMultiplierPort, EfiIdeHarddisk);
1871 
1872   if (Node == NULL) {
1873     return EFI_INVALID_PARAMETER;
1874   }
1875 
1876   //
1877   // Return success directly then upper layer driver could think reset device operation is done.
1878   //
1879   return EFI_SUCCESS;
1880 }
1881 
1882 /**
1883   Submit ATAPI request sense command.
1884 
1885   @param[in] This            A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
1886   @param[in] Target          The Target is an array of size TARGET_MAX_BYTES and it represents
1887                              the id of the SCSI device to send the SCSI Request Packet. Each
1888                              transport driver may choose to utilize a subset of this size to suit the needs
1889                              of transport target representation. For example, a Fibre Channel driver
1890                              may use only 8 bytes (WWN) to represent an FC target.
1891   @param[in] Lun             The LUN of the SCSI device to send the SCSI Request Packet.
1892   @param[in] SenseData       A pointer to store sense data.
1893   @param[in] SenseDataLength The sense data length.
1894   @param[in] Timeout         The timeout value to execute this cmd, uses 100ns as a unit.
1895 
1896   @retval EFI_SUCCESS        Send out the ATAPI packet command successfully.
1897   @retval EFI_DEVICE_ERROR   The device failed to send data.
1898 
1899 **/
1900 EFI_STATUS
1901 EFIAPI
AtaPacketRequestSense(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun,IN VOID * SenseData,IN UINT8 SenseDataLength,IN UINT64 Timeout)1902 AtaPacketRequestSense (
1903   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL         *This,
1904   IN  UINT8                                   *Target,
1905   IN  UINT64                                  Lun,
1906   IN  VOID                                    *SenseData,
1907   IN  UINT8                                   SenseDataLength,
1908   IN  UINT64                                  Timeout
1909   )
1910 {
1911   EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  Packet;
1912   UINT8                                       Cdb[12];
1913   EFI_STATUS                                  Status;
1914 
1915   ZeroMem (&Packet, sizeof (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
1916   ZeroMem (Cdb, 12);
1917 
1918   Cdb[0] = ATA_CMD_REQUEST_SENSE;
1919   Cdb[4] = SenseDataLength;
1920 
1921   Packet.Timeout          = Timeout;
1922   Packet.Cdb              = Cdb;
1923   Packet.CdbLength        = 12;
1924   Packet.DataDirection    = EFI_EXT_SCSI_DATA_DIRECTION_READ;
1925   Packet.InDataBuffer     = SenseData;
1926   Packet.InTransferLength = SenseDataLength;
1927 
1928   Status = ExtScsiPassThruPassThru (This, Target, Lun, &Packet, NULL);
1929 
1930   return Status;
1931 }
1932 
1933 /**
1934   Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
1935   supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
1936   nonblocking I/O functionality is optional.
1937 
1938   @param  This    A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
1939   @param  Target  The Target is an array of size TARGET_MAX_BYTES and it represents
1940                   the id of the SCSI device to send the SCSI Request Packet. Each
1941                   transport driver may choose to utilize a subset of this size to suit the needs
1942                   of transport target representation. For example, a Fibre Channel driver
1943                   may use only 8 bytes (WWN) to represent an FC target.
1944   @param  Lun     The LUN of the SCSI device to send the SCSI Request Packet.
1945   @param  Packet  A pointer to the SCSI Request Packet to send to the SCSI device
1946                   specified by Target and Lun.
1947   @param  Event   If nonblocking I/O is not supported then Event is ignored, and blocking
1948                   I/O is performed. If Event is NULL, then blocking I/O is performed. If
1949                   Event is not NULL and non blocking I/O is supported, then
1950                   nonblocking I/O is performed, and Event will be signaled when the
1951                   SCSI Request Packet completes.
1952 
1953   @retval EFI_SUCCESS           The SCSI Request Packet was sent by the host. For bi-directional
1954                                 commands, InTransferLength bytes were transferred from
1955                                 InDataBuffer. For write and bi-directional commands,
1956                                 OutTransferLength bytes were transferred by
1957                                 OutDataBuffer.
1958   @retval EFI_BAD_BUFFER_SIZE   The SCSI Request Packet was not executed. The number of bytes that
1959                                 could be transferred is returned in InTransferLength. For write
1960                                 and bi-directional commands, OutTransferLength bytes were
1961                                 transferred by OutDataBuffer.
1962   @retval EFI_NOT_READY         The SCSI Request Packet could not be sent because there are too many
1963                                 SCSI Request Packets already queued. The caller may retry again later.
1964   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SCSI Request
1965                                 Packet.
1966   @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.
1967   @retval EFI_UNSUPPORTED       The command described by the SCSI Request Packet is not supported
1968                                 by the host adapter. This includes the case of Bi-directional SCSI
1969                                 commands not supported by the implementation. The SCSI Request
1970                                 Packet was not sent, so no additional status information is available.
1971   @retval EFI_TIMEOUT           A timeout occurred while waiting for the SCSI Request Packet to execute.
1972 
1973 **/
1974 EFI_STATUS
1975 EFIAPI
ExtScsiPassThruPassThru(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun,IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET * Packet,IN EFI_EVENT Event OPTIONAL)1976 ExtScsiPassThruPassThru (
1977   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                    *This,
1978   IN UINT8                                              *Target,
1979   IN UINT64                                             Lun,
1980   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET     *Packet,
1981   IN EFI_EVENT                                          Event OPTIONAL
1982   )
1983 {
1984   EFI_STATUS                      Status;
1985   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
1986   UINT8                           Port;
1987   UINT8                           PortMultiplier;
1988   EFI_ATA_HC_WORK_MODE            Mode;
1989   LIST_ENTRY                      *Node;
1990   EFI_ATA_DEVICE_INFO             *DeviceInfo;
1991   BOOLEAN                         SenseReq;
1992   EFI_SCSI_SENSE_DATA             *PtrSenseData;
1993   UINTN                           SenseDataLen;
1994   EFI_STATUS                      SenseStatus;
1995 
1996   SenseDataLen = 0;
1997   Instance     = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
1998 
1999   if ((Packet == NULL) || (Packet->Cdb == NULL)) {
2000     return EFI_INVALID_PARAMETER;
2001   }
2002 
2003   //
2004   // Don't support variable length CDB
2005   //
2006   if ((Packet->CdbLength != 6) && (Packet->CdbLength != 10) &&
2007       (Packet->CdbLength != 12) && (Packet->CdbLength != 16)) {
2008     return EFI_INVALID_PARAMETER;
2009   }
2010 
2011   if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {
2012     return EFI_INVALID_PARAMETER;
2013   }
2014 
2015   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {
2016     return EFI_INVALID_PARAMETER;
2017   }
2018 
2019   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->OutDataBuffer, This->Mode->IoAlign)) {
2020     return EFI_INVALID_PARAMETER;
2021   }
2022 
2023   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->SenseData, This->Mode->IoAlign)) {
2024     return EFI_INVALID_PARAMETER;
2025   }
2026 
2027   //
2028   // For ATAPI device, doesn't support multiple LUN device.
2029   //
2030   if (Lun != 0) {
2031     return EFI_INVALID_PARAMETER;
2032   }
2033 
2034   //
2035   // The layout of Target array:
2036   //  ________________________________________________________________________
2037   // |       Byte 0        |       Byte 1        | ... | TARGET_MAX_BYTES - 1 |
2038   // |_____________________|_____________________|_____|______________________|
2039   // |                     | The port multiplier |     |                      |
2040   // |   The port number   |    port number      | N/A |         N/A          |
2041   // |_____________________|_____________________|_____|______________________|
2042   //
2043   // For ATAPI device, 2 bytes is enough to represent the location of SCSI device.
2044   //
2045   Port           = Target[0];
2046   PortMultiplier = Target[1];
2047 
2048   Node = SearchDeviceInfoList(Instance, Port, PortMultiplier, EfiIdeCdrom);
2049   if (Node == NULL) {
2050     return EFI_INVALID_PARAMETER;
2051   }
2052 
2053   DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
2054 
2055   //
2056   // ATA_CMD_IDENTIFY_DEVICE cmd is a ATA cmd but not a SCSI cmd.
2057   // Normally it should NOT be passed down through ExtScsiPassThru protocol interface.
2058   // But to response EFI_DISK_INFO.Identify() request from ScsiDisk, we should handle this command.
2059   //
2060   if (*((UINT8*)Packet->Cdb) == ATA_CMD_IDENTIFY_DEVICE) {
2061     CopyMem (Packet->InDataBuffer, DeviceInfo->IdentifyData, sizeof (EFI_IDENTIFY_DATA));
2062     //
2063     // For IDENTIFY DEVICE cmd, we don't need to get sense data.
2064     //
2065     Packet->SenseDataLength = 0;
2066     return EFI_SUCCESS;
2067   }
2068 
2069   Mode = Instance->Mode;
2070   switch (Mode) {
2071     case EfiAtaIdeMode:
2072       //
2073       // Reassign IDE mode io port registers' base addresses
2074       //
2075       Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
2076 
2077       if (EFI_ERROR (Status)) {
2078         return Status;
2079       }
2080 
2081       Status = AtaPacketCommandExecute (Instance->PciIo, &Instance->IdeRegisters[Port], Port, PortMultiplier, Packet);
2082       break;
2083     case EfiAtaAhciMode:
2084       if (PortMultiplier == 0xFF) {
2085         //
2086         // If there is no port multiplier, the PortMultiplier will be 0xFF
2087         // Here, we convert its value to 0 to follow the AHCI spec.
2088         //
2089         PortMultiplier = 0;
2090       }
2091       Status = AhciPacketCommandExecute (Instance->PciIo, &Instance->AhciRegisters, Port, PortMultiplier, Packet);
2092       break;
2093     default :
2094       Status = EFI_DEVICE_ERROR;
2095       break;
2096   }
2097 
2098   //
2099   // If the cmd doesn't get executed correctly, then check sense data.
2100   //
2101   if (EFI_ERROR (Status) && (Packet->SenseDataLength != 0) && (*((UINT8*)Packet->Cdb) != ATA_CMD_REQUEST_SENSE)) {
2102     PtrSenseData = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)), This->Mode->IoAlign);
2103     if (PtrSenseData == NULL) {
2104       return EFI_DEVICE_ERROR;
2105     }
2106 
2107     for (SenseReq = TRUE; SenseReq;) {
2108       SenseStatus = AtaPacketRequestSense (
2109                       This,
2110                       Target,
2111                       Lun,
2112                       PtrSenseData,
2113                       sizeof (EFI_SCSI_SENSE_DATA),
2114                       Packet->Timeout
2115                       );
2116       if (EFI_ERROR (SenseStatus)) {
2117         break;
2118       }
2119 
2120       CopyMem ((UINT8*)Packet->SenseData + SenseDataLen, PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));
2121       SenseDataLen += sizeof (EFI_SCSI_SENSE_DATA);
2122 
2123       //
2124       // no more sense key or number of sense keys exceeds predefined,
2125       // skip the loop.
2126       //
2127       if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
2128           (SenseDataLen + sizeof (EFI_SCSI_SENSE_DATA) > Packet->SenseDataLength)) {
2129         SenseReq = FALSE;
2130       }
2131     }
2132     FreeAlignedPages (PtrSenseData, EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)));
2133   }
2134   //
2135   // Update the SenseDataLength field to the data length received.
2136   //
2137   Packet->SenseDataLength = (UINT8)SenseDataLen;
2138   return Status;
2139 }
2140 
2141 /**
2142   Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
2143   can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
2144   Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
2145   Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
2146   channel.
2147 
2148   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2149   @param  Target On input, a pointer to the Target ID (an array of size
2150                  TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
2151                  On output, a pointer to the Target ID (an array of
2152                  TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
2153                  channel. An input value of 0xF(all bytes in the array are 0xF) in the
2154                  Target array retrieves the Target ID of the first SCSI device present on a
2155                  SCSI channel.
2156   @param  Lun    On input, a pointer to the LUN of a SCSI device present on the SCSI
2157                  channel. On output, a pointer to the LUN of the next SCSI device present
2158                  on a SCSI channel.
2159 
2160   @retval EFI_SUCCESS           The Target ID and LUN of the next SCSI device on the SCSI
2161                                 channel was returned in Target and Lun.
2162   @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
2163                                 not returned on a previous call to GetNextTargetLun().
2164   @retval EFI_NOT_FOUND         There are no more SCSI devices on this SCSI channel.
2165 
2166 **/
2167 EFI_STATUS
2168 EFIAPI
ExtScsiPassThruGetNextTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN OUT UINT8 ** Target,IN OUT UINT64 * Lun)2169 ExtScsiPassThruGetNextTargetLun (
2170   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
2171   IN OUT UINT8                           **Target,
2172   IN OUT UINT64                          *Lun
2173   )
2174 {
2175   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
2176   LIST_ENTRY                      *Node;
2177   EFI_ATA_DEVICE_INFO             *DeviceInfo;
2178   UINT8                           *Target8;
2179   UINT16                          *Target16;
2180 
2181   Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
2182 
2183   if (Target == NULL || Lun == NULL) {
2184     return EFI_INVALID_PARAMETER;
2185   }
2186 
2187   if (*Target == NULL) {
2188     return EFI_INVALID_PARAMETER;
2189   }
2190 
2191   Target8  = *Target;
2192   Target16 = (UINT16 *)*Target;
2193 
2194   if (CompareMem(Target8, mScsiId, TARGET_MAX_BYTES) != 0) {
2195     //
2196     // For ATAPI device, we use 2 least significant bytes to represent the location of SCSI device.
2197     // So the higher bytes in Target array should be 0xFF.
2198     //
2199     if (CompareMem (&Target8[2], &mScsiId[2], TARGET_MAX_BYTES - 2) != 0) {
2200       return EFI_INVALID_PARAMETER;
2201     }
2202 
2203     //
2204     // When Target is not all 0xFF's, compare 2 least significant bytes with
2205     // previous target id to see if it is returned by previous call.
2206     //
2207     if ((*Target16 != Instance->PreviousTargetId) ||
2208         (*Lun != Instance->PreviousLun)) {
2209       return EFI_INVALID_PARAMETER;
2210     }
2211 
2212     //
2213     // Traverse the whole device list to find the next cdrom closed to
2214     // the device signified by Target[0] and Target[1].
2215     //
2216     // Note that we here use a tricky way to find the next cdrom :
2217     // All ata devices are detected and inserted into the device list
2218     // sequentially.
2219     //
2220     Node = GetFirstNode (&Instance->DeviceList);
2221 
2222     while (!IsNull (&Instance->DeviceList, Node)) {
2223       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
2224 
2225       if ((DeviceInfo->Type == EfiIdeCdrom) &&
2226          ((Target8[0] < DeviceInfo->Port) ||
2227           ((Target8[0] == DeviceInfo->Port) &&
2228            (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {
2229         Target8[0] = (UINT8)DeviceInfo->Port;
2230         Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
2231         goto Exit;
2232       }
2233 
2234       Node = GetNextNode (&Instance->DeviceList, Node);
2235     }
2236 
2237     return EFI_NOT_FOUND;
2238   } else {
2239     //
2240     // If the array is all 0xFF's, start to traverse the device list from the beginning
2241     //
2242     Node = GetFirstNode (&Instance->DeviceList);
2243     while (!IsNull (&Instance->DeviceList, Node)) {
2244       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
2245 
2246       if (DeviceInfo->Type == EfiIdeCdrom) {
2247         Target8[0] = (UINT8)DeviceInfo->Port;
2248         Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
2249         goto Exit;
2250       }
2251 
2252       Node = GetNextNode (&Instance->DeviceList, Node);
2253     }
2254 
2255     return EFI_NOT_FOUND;
2256   }
2257 
2258 Exit:
2259   *Lun = 0;
2260 
2261   //
2262   // Update the PreviousTargetId.
2263   //
2264   Instance->PreviousTargetId = *Target16;
2265   Instance->PreviousLun      = *Lun;
2266 
2267   return EFI_SUCCESS;
2268 }
2269 
2270 /**
2271   Used to allocate and build a device path node for a SCSI device on a SCSI channel.
2272 
2273   @param  This       A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2274   @param  Target     The Target is an array of size TARGET_MAX_BYTES and it specifies the
2275                      Target ID of the SCSI device for which a device path node is to be
2276                      allocated and built. Transport drivers may chose to utilize a subset of
2277                      this size to suit the representation of targets. For example, a Fibre
2278                      Channel driver may use only 8 bytes (WWN) in the array to represent a
2279                      FC target.
2280   @param  Lun        The LUN of the SCSI device for which a device path node is to be
2281                      allocated and built.
2282   @param  DevicePath A pointer to a single device path node that describes the SCSI device
2283                      specified by Target and Lun. This function is responsible for
2284                      allocating the buffer DevicePath with the boot service
2285                      AllocatePool(). It is the caller's responsibility to free
2286                      DevicePath when the caller is finished with DevicePath.
2287 
2288   @retval EFI_SUCCESS           The device path node that describes the SCSI device specified by
2289                                 Target and Lun was allocated and returned in
2290                                 DevicePath.
2291   @retval EFI_INVALID_PARAMETER DevicePath is NULL.
2292   @retval EFI_NOT_FOUND         The SCSI devices specified by Target and Lun does not exist
2293                                 on the SCSI channel.
2294   @retval EFI_OUT_OF_RESOURCES  There are not enough resources to allocate DevicePath.
2295 
2296 **/
2297 EFI_STATUS
2298 EFIAPI
ExtScsiPassThruBuildDevicePath(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun,IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath)2299 ExtScsiPassThruBuildDevicePath (
2300   IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
2301   IN     UINT8                              *Target,
2302   IN     UINT64                             Lun,
2303   IN OUT EFI_DEVICE_PATH_PROTOCOL           **DevicePath
2304   )
2305 {
2306   EFI_DEV_PATH                    *DevicePathNode;
2307   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
2308   UINT8                           Port;
2309   UINT8                           PortMultiplier;
2310 
2311   Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
2312 
2313   Port           = Target[0];
2314   PortMultiplier = Target[1];
2315 
2316   //
2317   // Validate parameters passed in.
2318   //
2319   if (DevicePath == NULL) {
2320     return EFI_INVALID_PARAMETER;
2321   }
2322 
2323   //
2324   // can not build device path for the SCSI Host Controller.
2325   //
2326   if (Lun != 0) {
2327     return EFI_NOT_FOUND;
2328   }
2329 
2330   if (SearchDeviceInfoList(Instance, Port, PortMultiplier, EfiIdeCdrom) == NULL) {
2331     return EFI_NOT_FOUND;
2332   }
2333 
2334   if (Instance->Mode == EfiAtaIdeMode) {
2335     DevicePathNode = AllocateCopyPool (sizeof (ATAPI_DEVICE_PATH), &mAtapiDevicePathTemplate);
2336     if (DevicePathNode == NULL) {
2337       return EFI_OUT_OF_RESOURCES;
2338     }
2339 
2340     DevicePathNode->Atapi.PrimarySecondary = Port;
2341     DevicePathNode->Atapi.SlaveMaster      = PortMultiplier;
2342     DevicePathNode->Atapi.Lun              = (UINT16) Lun;
2343   } else {
2344     DevicePathNode = AllocateCopyPool (sizeof (SATA_DEVICE_PATH), &mSataDevicePathTemplate);
2345     if (DevicePathNode == NULL) {
2346       return EFI_OUT_OF_RESOURCES;
2347     }
2348 
2349     DevicePathNode->Sata.HBAPortNumber            = Port;
2350     //
2351     // For CD-ROM working in the AHCI mode, only 8 bits are used to record
2352     // the PortMultiplier information. If the CD-ROM is directly attached
2353     // on a SATA port, the PortMultiplier should be translated from 0xFF
2354     // to 0xFFFF according to the UEFI spec.
2355     //
2356     DevicePathNode->Sata.PortMultiplierPortNumber = PortMultiplier == 0xFF ? 0xFFFF : PortMultiplier;
2357     DevicePathNode->Sata.Lun                      = (UINT16) Lun;
2358   }
2359 
2360   *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathNode;
2361 
2362   return EFI_SUCCESS;
2363 }
2364 
2365 /**
2366   Used to translate a device path node to a Target ID and LUN.
2367 
2368   @param  This       A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2369   @param  DevicePath A pointer to a single device path node that describes the SCSI device
2370                      on the SCSI channel.
2371   @param  Target     A pointer to the Target Array which represents the ID of a SCSI device
2372                      on the SCSI channel.
2373   @param  Lun        A pointer to the LUN of a SCSI device on the SCSI channel.
2374 
2375   @retval EFI_SUCCESS           DevicePath was successfully translated to a Target ID and
2376                                 LUN, and they were returned in Target and Lun.
2377   @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.
2378   @retval EFI_NOT_FOUND         A valid translation from DevicePath to a Target ID and LUN
2379                                 does not exist.
2380   @retval EFI_UNSUPPORTED       This driver does not support the device path node type in
2381                                  DevicePath.
2382 
2383 **/
2384 EFI_STATUS
2385 EFIAPI
ExtScsiPassThruGetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,OUT UINT8 ** Target,OUT UINT64 * Lun)2386 ExtScsiPassThruGetTargetLun (
2387   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
2388   IN  EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
2389   OUT UINT8                              **Target,
2390   OUT UINT64                             *Lun
2391   )
2392 {
2393   EFI_DEV_PATH                    *DevicePathNode;
2394   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
2395   LIST_ENTRY                      *Node;
2396 
2397   Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
2398 
2399   //
2400   // Validate parameters passed in.
2401   //
2402   if (DevicePath == NULL || Target == NULL || Lun == NULL) {
2403     return EFI_INVALID_PARAMETER;
2404   }
2405 
2406   if (*Target == NULL) {
2407     return EFI_INVALID_PARAMETER;
2408   }
2409   //
2410   // Check whether the DevicePath belongs to SCSI_DEVICE_PATH
2411   //
2412   if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
2413       ((DevicePath->SubType != MSG_ATAPI_DP) &&
2414       (DevicePath->SubType != MSG_SATA_DP)) ||
2415       ((DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH)) &&
2416       (DevicePathNodeLength(DevicePath) != sizeof(SATA_DEVICE_PATH)))) {
2417     return EFI_UNSUPPORTED;
2418   }
2419 
2420   SetMem (*Target, TARGET_MAX_BYTES, 0xFF);
2421 
2422   DevicePathNode = (EFI_DEV_PATH *) DevicePath;
2423 
2424   if (Instance->Mode == EfiAtaIdeMode) {
2425     (*Target)[0] = (UINT8) DevicePathNode->Atapi.PrimarySecondary;
2426     (*Target)[1] = (UINT8) DevicePathNode->Atapi.SlaveMaster;
2427     *Lun         = (UINT8) DevicePathNode->Atapi.Lun;
2428   } else {
2429     (*Target)[0] = (UINT8) DevicePathNode->Sata.HBAPortNumber;
2430     (*Target)[1] = (UINT8) DevicePathNode->Sata.PortMultiplierPortNumber;
2431     *Lun         = (UINT8) DevicePathNode->Sata.Lun;
2432   }
2433 
2434   Node = SearchDeviceInfoList(Instance, (*Target)[0], (*Target)[1], EfiIdeCdrom);
2435 
2436   if (Node == NULL) {
2437     return EFI_NOT_FOUND;
2438   }
2439 
2440   if (*Lun != 0) {
2441     return EFI_NOT_FOUND;
2442   }
2443 
2444   return EFI_SUCCESS;
2445 }
2446 
2447 /**
2448   Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.
2449 
2450   @param  This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2451 
2452   @retval EFI_SUCCESS      The SCSI channel was reset.
2453   @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.
2454   @retval EFI_TIMEOUT      A timeout occurred while attempting to reset the SCSI channel.
2455   @retval EFI_UNSUPPORTED  The SCSI channel does not support a channel reset operation.
2456 
2457 **/
2458 EFI_STATUS
2459 EFIAPI
ExtScsiPassThruResetChannel(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This)2460 ExtScsiPassThruResetChannel (
2461   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL   *This
2462   )
2463 {
2464   //
2465   // Return success directly then upper layer driver could think reset channel operation is done.
2466   //
2467   return EFI_SUCCESS;
2468 }
2469 
2470 /**
2471   Resets a SCSI logical unit that is connected to a SCSI channel.
2472 
2473   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2474   @param  Target The Target is an array of size TARGET_MAX_BYTE and it represents the
2475                  target port ID of the SCSI device containing the SCSI logical unit to
2476                  reset. Transport drivers may chose to utilize a subset of this array to suit
2477                  the representation of their targets.
2478   @param  Lun    The LUN of the SCSI device to reset.
2479 
2480   @retval EFI_SUCCESS           The SCSI device specified by Target and Lun was reset.
2481   @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
2482   @retval EFI_TIMEOUT           A timeout occurred while attempting to reset the SCSI device
2483                                 specified by Target and Lun.
2484   @retval EFI_UNSUPPORTED       The SCSI channel does not support a target reset operation.
2485   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to reset the SCSI device
2486                                  specified by Target and Lun.
2487 
2488 **/
2489 EFI_STATUS
2490 EFIAPI
ExtScsiPassThruResetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun)2491 ExtScsiPassThruResetTargetLun (
2492   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
2493   IN UINT8                              *Target,
2494   IN UINT64                             Lun
2495   )
2496 {
2497   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
2498   LIST_ENTRY                      *Node;
2499   UINT8                           Port;
2500   UINT8                           PortMultiplier;
2501 
2502   Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
2503   //
2504   // For ATAPI device, doesn't support multiple LUN device.
2505   //
2506   if (Lun != 0) {
2507     return EFI_INVALID_PARAMETER;
2508   }
2509   //
2510   // The layout of Target array:
2511   //  ________________________________________________________________________
2512   // |       Byte 0        |       Byte 1        | ... | TARGET_MAX_BYTES - 1 |
2513   // |_____________________|_____________________|_____|______________________|
2514   // |                     | The port multiplier |     |                      |
2515   // |   The port number   |    port number      | N/A |         N/A          |
2516   // |_____________________|_____________________|_____|______________________|
2517   //
2518   // For ATAPI device, 2 bytes is enough to represent the location of SCSI device.
2519   //
2520   Port           = Target[0];
2521   PortMultiplier = Target[1];
2522 
2523   Node = SearchDeviceInfoList(Instance, Port, PortMultiplier, EfiIdeCdrom);
2524   if (Node == NULL) {
2525     return EFI_INVALID_PARAMETER;
2526   }
2527 
2528   //
2529   // Return success directly then upper layer driver could think reset target LUN operation is done.
2530   //
2531   return EFI_SUCCESS;
2532 }
2533 
2534 /**
2535   Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
2536   be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs
2537   for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to
2538   see if a SCSI device is actually present at that location on the SCSI channel.
2539 
2540   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
2541   @param  Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
2542                  On output, a pointer to the Target ID (an array of
2543                  TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
2544                  channel. An input value of 0xF(all bytes in the array are 0xF) in the
2545                  Target array retrieves the Target ID of the first SCSI device present on a
2546                  SCSI channel.
2547 
2548   @retval EFI_SUCCESS           The Target ID of the next SCSI device on the SCSI
2549                                 channel was returned in Target.
2550   @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
2551   @retval EFI_TIMEOUT           Target array is not all 0xF, and Target was not
2552                                 returned on a previous call to GetNextTarget().
2553   @retval EFI_NOT_FOUND         There are no more SCSI devices on this SCSI channel.
2554 
2555 **/
2556 EFI_STATUS
2557 EFIAPI
ExtScsiPassThruGetNextTarget(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN OUT UINT8 ** Target)2558 ExtScsiPassThruGetNextTarget (
2559   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
2560   IN OUT UINT8                           **Target
2561   )
2562 {
2563   ATA_ATAPI_PASS_THRU_INSTANCE    *Instance;
2564   LIST_ENTRY                      *Node;
2565   EFI_ATA_DEVICE_INFO             *DeviceInfo;
2566   UINT8                           *Target8;
2567   UINT16                          *Target16;
2568 
2569   Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
2570 
2571   if (Target == NULL || *Target == NULL) {
2572     return EFI_INVALID_PARAMETER;
2573   }
2574 
2575   Target8  = *Target;
2576   Target16 = (UINT16 *)*Target;
2577 
2578   if (CompareMem(Target8, mScsiId, TARGET_MAX_BYTES) != 0) {
2579     //
2580     // For ATAPI device, we use 2 least significant bytes to represent the location of SCSI device.
2581     // So the higher bytes in Target array should be 0xFF.
2582     //
2583     if (CompareMem (&Target8[2], &mScsiId[2], TARGET_MAX_BYTES - 2) != 0) {
2584       return EFI_INVALID_PARAMETER;
2585     }
2586 
2587     //
2588     // When Target is not all 0xFF's, compare 2 least significant bytes with
2589     // previous target id to see if it is returned by previous call.
2590     //
2591     if (*Target16 != Instance->PreviousTargetId) {
2592       return EFI_INVALID_PARAMETER;
2593     }
2594 
2595     //
2596     // Traverse the whole device list to find the next cdrom closed to
2597     // the device signified by Target[0] and Target[1].
2598     //
2599     // Note that we here use a tricky way to find the next cdrom :
2600     // All ata devices are detected and inserted into the device list
2601     // sequentially.
2602     //
2603     Node = GetFirstNode (&Instance->DeviceList);
2604     while (!IsNull (&Instance->DeviceList, Node)) {
2605       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
2606 
2607       if ((DeviceInfo->Type == EfiIdeCdrom) &&
2608          ((Target8[0] < DeviceInfo->Port) ||
2609           ((Target8[0] == DeviceInfo->Port) &&
2610            (Target8[1] < (UINT8)DeviceInfo->PortMultiplier)))) {
2611         Target8[0] = (UINT8)DeviceInfo->Port;
2612         Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
2613         goto Exit;
2614       }
2615 
2616       Node = GetNextNode (&Instance->DeviceList, Node);
2617     }
2618 
2619     return EFI_NOT_FOUND;
2620   } else {
2621     //
2622     // If the array is all 0xFF's, start to traverse the device list from the beginning
2623     //
2624     Node = GetFirstNode (&Instance->DeviceList);
2625 
2626     while (!IsNull (&Instance->DeviceList, Node)) {
2627       DeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);
2628 
2629       if (DeviceInfo->Type == EfiIdeCdrom) {
2630         Target8[0] = (UINT8)DeviceInfo->Port;
2631         Target8[1] = (UINT8)DeviceInfo->PortMultiplier;
2632         goto Exit;
2633       }
2634 
2635       Node = GetNextNode (&Instance->DeviceList, Node);
2636     }
2637 
2638     return EFI_NOT_FOUND;
2639   }
2640 
2641 Exit:
2642   //
2643   // Update the PreviousTargetId.
2644   //
2645   Instance->PreviousTargetId = *Target16;
2646 
2647   return EFI_SUCCESS;
2648 }
2649 
2650