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