1 /** @file
2   This file implement UEFI driver for IDE Bus which includes device identification,
3   Child device(Disk, CDROM, etc) enumeration and child handler installation, and
4   driver stop.
5 
6   Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9   @par Revision Reference:
10   This module is modified from DXE\IDE module for Ide Contriller Init support
11 
12 **/
13 
14 #include "IdeBus.h"
15 
16 #define PCI_CLASS_MASS_STORAGE  0x01
17 #define PCI_SUB_CLASS_IDE       0x01
18 
19 
20 //
21 // IDE Bus Driver Binding Protocol Instance
22 //
23 EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
24   IDEBusDriverBindingSupported,
25   IDEBusDriverBindingStart,
26   IDEBusDriverBindingStop,
27   0xa,
28   NULL,
29   NULL
30 };
31 /**
32   Deregister an IDE device and free resources
33 
34   @param  This Protocol instance pointer.
35   @param  Controller Ide device handle
36   @param  Handle Handle of device to deregister driver on
37 
38   @retval EFI_SUCCESS  Deregiter a specific IDE device successfully
39 
40 
41 **/
42 EFI_STATUS
DeRegisterIdeDevice(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_HANDLE Handle)43 DeRegisterIdeDevice (
44   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
45   IN  EFI_HANDLE                     Controller,
46   IN  EFI_HANDLE                     Handle
47   )
48 {
49   EFI_STATUS            Status;
50   EFI_BLOCK_IO_PROTOCOL *BlkIo;
51   IDE_BLK_IO_DEV        *IdeBlkIoDevice;
52   EFI_PCI_IO_PROTOCOL   *PciIo;
53   UINTN                 Index;
54 
55   Status = gBS->OpenProtocol (
56                   Handle,
57                   &gEfiBlockIoProtocolGuid,
58                   (VOID **) &BlkIo,
59                   This->DriverBindingHandle,
60                   Controller,
61                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
62                   );
63   if (EFI_ERROR (Status)) {
64     return Status;
65   }
66 
67   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
68 
69   //
70   // Report Status code: Device disabled
71   //
72   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
73     EFI_PROGRESS_CODE,
74     (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
75     IdeBlkIoDevice->DevicePath
76     );
77 
78   //
79   // Close the child handle
80   //
81   Status = gBS->CloseProtocol (
82                   Controller,
83                   &gEfiPciIoProtocolGuid,
84                   This->DriverBindingHandle,
85                   Handle
86                   );
87 
88   Status = gBS->UninstallMultipleProtocolInterfaces (
89                   Handle,
90                   &gEfiDevicePathProtocolGuid,
91                   IdeBlkIoDevice->DevicePath,
92                   &gEfiBlockIoProtocolGuid,
93                   &IdeBlkIoDevice->BlkIo,
94                   &gEfiDiskInfoProtocolGuid,
95                   &IdeBlkIoDevice->DiskInfo,
96                   NULL
97                   );
98 
99   if (EFI_ERROR (Status)) {
100     gBS->OpenProtocol (
101           Controller,
102           &gEfiPciIoProtocolGuid,
103           (VOID **) &PciIo,
104           This->DriverBindingHandle,
105           Handle,
106           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
107           );
108     return Status;
109   }
110 
111   //
112   // Release allocated resources
113   //
114   Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
115   if (Index < MAX_IDE_DEVICE) {
116     IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
117   }
118   ReleaseIdeResources (IdeBlkIoDevice);
119 
120   return EFI_SUCCESS;
121 }
122 /**
123   Supported function of Driver Binding protocol for this driver.
124 
125   @param This                A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
126   @param ControllerHandle    The handle of the controller to test.
127   @param RemainingDevicePath A pointer to the remaining portion of a device path.
128 
129   @retval  EFI_SUCCESS Driver loaded.
130   @retval  other       Driver not loaded.
131 
132 **/
133 EFI_STATUS
134 EFIAPI
IDEBusDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)135 IDEBusDriverBindingSupported (
136   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
137   IN EFI_HANDLE                   Controller,
138   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
139   )
140 {
141   EFI_STATUS                        Status;
142   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
143   EFI_DEV_PATH                      *Node;
144   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
145   EFI_PCI_IO_PROTOCOL               *PciIo;
146   PCI_TYPE00                        PciData;
147 
148   if (RemainingDevicePath != NULL) {
149     Node = (EFI_DEV_PATH *) RemainingDevicePath;
150     //
151     // Check if RemainingDevicePath is the End of Device Path Node,
152     // if yes, go on checking other conditions
153     //
154     if (!IsDevicePathEnd (Node)) {
155       //
156       // If RemainingDevicePath isn't the End of Device Path Node,
157       // check its validation
158       //
159       if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
160           Node->DevPath.SubType != MSG_ATAPI_DP ||
161           DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
162         return EFI_UNSUPPORTED;
163       }
164     }
165   }
166 
167   //
168   // Verify the Ide Controller Init Protocol, which installed by the
169   // IdeController module.
170   //
171   Status = gBS->OpenProtocol (
172                   Controller,
173                   &gEfiIdeControllerInitProtocolGuid,
174                   (VOID **) &IdeInit,
175                   This->DriverBindingHandle,
176                   Controller,
177                   EFI_OPEN_PROTOCOL_BY_DRIVER
178                   );
179 
180   if (Status == EFI_ALREADY_STARTED) {
181     return EFI_SUCCESS;
182   }
183 
184   if (EFI_ERROR (Status)) {
185     return Status;
186   }
187 
188   //
189   // Close the I/O Abstraction(s) used to perform the supported test
190   //
191   gBS->CloseProtocol (
192         Controller,
193         &gEfiIdeControllerInitProtocolGuid,
194         This->DriverBindingHandle,
195         Controller
196         );
197 
198   //
199   // Open the EFI Device Path protocol needed to perform the supported test
200   //
201   Status = gBS->OpenProtocol (
202                   Controller,
203                   &gEfiDevicePathProtocolGuid,
204                   (VOID **) &ParentDevicePath,
205                   This->DriverBindingHandle,
206                   Controller,
207                   EFI_OPEN_PROTOCOL_BY_DRIVER
208                   );
209   if (Status == EFI_ALREADY_STARTED) {
210     return EFI_SUCCESS;
211   }
212 
213   //
214   // Close protocol, don't use device path protocol in the Support() function
215   //
216   gBS->CloseProtocol (
217         Controller,
218         &gEfiDevicePathProtocolGuid,
219         This->DriverBindingHandle,
220         Controller
221         );
222 
223   //
224   // Get the EfiPciIoProtocol
225   //
226   Status = gBS->OpenProtocol (
227                   Controller,
228                   &gEfiPciIoProtocolGuid,
229                   (VOID **) &PciIo,
230                   This->DriverBindingHandle,
231                   Controller,
232                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
233                   );
234 
235   if (EFI_ERROR (Status)) {
236     return Status;
237   }
238 
239   //
240   // Now further check the PCI header: Base class (offset 0x0B) and
241   // Sub Class (offset 0x0A). This controller should be an IDE controller
242   //
243   Status = PciIo->Pci.Read (
244                         PciIo,
245                         EfiPciIoWidthUint8,
246                         0,
247                         sizeof (PciData),
248                         &PciData
249                         );
250 
251   if (!EFI_ERROR (Status)) {
252     //
253     // Examine if it is IDE mode by class code
254     //
255     if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)) {
256       Status = EFI_UNSUPPORTED;
257     } else {
258       Status = EFI_SUCCESS;
259     }
260   }
261 
262   return Status;
263 }
264 
265 
266 /**
267   Start function of Driver binding protocol which start this driver on Controller
268   by detecting all disks and installing BlockIo protocol on them.
269 
270   @param  This                Protocol instance pointer.
271   @param  Controller          Handle of device to bind driver to.
272   @param  RemainingDevicePath produce all possible children.
273 
274   @retval  EFI_SUCCESS         This driver is added to ControllerHandle.
275   @retval  EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
276   @retval  other               This driver does not support this device.
277 
278 **/
279 EFI_STATUS
280 EFIAPI
IDEBusDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)281 IDEBusDriverBindingStart (
282   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
283   IN EFI_HANDLE                   Controller,
284   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
285   )
286 {
287   EFI_STATUS                        Status;
288   EFI_STATUS                        SavedStatus;
289   EFI_PCI_IO_PROTOCOL               *PciIo;
290   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
291   EFI_DEV_PATH                      *Node;
292   UINT8                             IdeChannel;
293   UINT8                             BeginningIdeChannel;
294   UINT8                             EndIdeChannel;
295   UINT8                             IdeDevice;
296   UINT8                             BeginningIdeDevice;
297   UINT8                             EndIdeDevice;
298   IDE_BLK_IO_DEV                    *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
299   IDE_BLK_IO_DEV                    *IdeBlkIoDevicePtr;
300   IDE_REGISTERS_BASE_ADDR           IdeRegsBaseAddr[IdeMaxChannel];
301   ATA_TRANSFER_MODE                 TransferMode;
302   ATA_DRIVE_PARMS                   DriveParameters;
303   EFI_DEV_PATH                      NewNode;
304   UINT8                             ConfigurationOptions;
305   UINT16                            CommandBlockBaseAddr;
306   UINT16                            ControlBlockBaseAddr;
307   UINTN                             DataSize;
308   IDE_BUS_DRIVER_PRIVATE_DATA       *IdeBusDriverPrivateData;
309   UINT64                            Supports;
310 
311   //
312   // Local variables declaration for IdeControllerInit support
313   //
314   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
315   BOOLEAN                           EnumAll;
316   BOOLEAN                           ChannelEnabled;
317   UINT8                             MaxDevices;
318   EFI_IDENTIFY_DATA                 IdentifyData;
319   EFI_ATA_COLLECTIVE_MODE           *SupportedModes;
320 
321   IdeBusDriverPrivateData = NULL;
322   SupportedModes          = NULL;
323 
324   //
325   // Perform IdeBus initialization
326   //
327   Status = gBS->OpenProtocol (
328                   Controller,
329                   &gEfiDevicePathProtocolGuid,
330                   (VOID **) &ParentDevicePath,
331                   This->DriverBindingHandle,
332                   Controller,
333                   EFI_OPEN_PROTOCOL_BY_DRIVER
334                   );
335   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
336     return Status;
337   }
338 
339   //
340   // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
341   //
342   Status = gBS->OpenProtocol (
343                   Controller,
344                   &gEfiIdeControllerInitProtocolGuid,
345                   (VOID **) &IdeInit,
346                   This->DriverBindingHandle,
347                   Controller,
348                   EFI_OPEN_PROTOCOL_BY_DRIVER
349                   );
350 
351   //
352   // The following OpenProtocol function with _GET_PROTOCOL attribute and
353   // will not return EFI_ALREADY_STARTED, so save it for now
354   //
355   SavedStatus = Status;
356 
357   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
358     DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
359     //
360     // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
361     //
362     goto ErrorExit;
363   }
364 
365   //
366   // Save Enumall. Step7.2
367   //
368   EnumAll       = IdeInit->EnumAll;
369 
370   //
371   // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
372   // attribute will not return EFI_ALREADY_STARTED
373   //
374   Status = gBS->OpenProtocol (
375                   Controller,
376                   &gEfiPciIoProtocolGuid,
377                   (VOID **) &PciIo,
378                   This->DriverBindingHandle,
379                   Controller,
380                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
381                   );
382   if (EFI_ERROR (Status)) {
383     DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
384     goto ErrorExit;
385   }
386 
387   //
388   // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
389   //
390   if (SavedStatus != EFI_ALREADY_STARTED) {
391     IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
392     if (IdeBusDriverPrivateData == NULL) {
393       Status = EFI_OUT_OF_RESOURCES;
394       goto ErrorExit;
395     }
396 
397     ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
398     Status = gBS->InstallMultipleProtocolInterfaces (
399                     &Controller,
400                     &gEfiCallerIdGuid,
401                     IdeBusDriverPrivateData,
402                     NULL
403                     );
404     if (EFI_ERROR (Status)) {
405       goto ErrorExit;
406     }
407 
408   } else {
409     Status = gBS->OpenProtocol (
410                     Controller,
411                     &gEfiCallerIdGuid,
412                     (VOID **) &IdeBusDriverPrivateData,
413                     This->DriverBindingHandle,
414                     Controller,
415                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
416                     );
417     if (EFI_ERROR (Status)) {
418       IdeBusDriverPrivateData = NULL;
419       goto ErrorExit;
420     }
421   }
422 
423   Status = PciIo->Attributes (
424                     PciIo,
425                     EfiPciIoAttributeOperationSupported,
426                     0,
427                     &Supports
428                     );
429   if (!EFI_ERROR (Status)) {
430     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
431     Status = PciIo->Attributes (
432                       PciIo,
433                       EfiPciIoAttributeOperationEnable,
434                       Supports,
435                       NULL
436                       );
437   }
438 
439   if (EFI_ERROR (Status)) {
440     goto ErrorExit;
441   }
442 
443   //
444   // Read the environment variable that contains the IDEBus Driver's
445   // Config options that were set by the Driver Configuration Protocol
446   //
447   DataSize = sizeof (ConfigurationOptions);
448   Status = gRT->GetVariable (
449                   (CHAR16 *) L"Configuration",
450                   &gEfiCallerIdGuid,
451                   NULL,
452                   &DataSize,
453                   &ConfigurationOptions
454                   );
455   if (EFI_ERROR (Status)) {
456     ConfigurationOptions = 0x0f;
457   }
458 
459    if (EnumAll || RemainingDevicePath == NULL) {
460     //
461     // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,
462     // must enumerate all IDE devices anyway
463     //
464     BeginningIdeChannel = IdePrimary;
465     EndIdeChannel       = IdeSecondary;
466     BeginningIdeDevice  = IdeMaster;
467     EndIdeDevice        = IdeSlave;
468 
469   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
470     //
471     // If RemainingDevicePath isn't the End of Device Path Node,
472     // only scan the specified device by RemainingDevicePath
473     //
474     Node                = (EFI_DEV_PATH *) RemainingDevicePath;
475     BeginningIdeChannel = Node->Atapi.PrimarySecondary;
476     EndIdeChannel       = BeginningIdeChannel;
477     BeginningIdeDevice  = Node->Atapi.SlaveMaster;
478     EndIdeDevice        = BeginningIdeDevice;
479     if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {
480       Status = EFI_INVALID_PARAMETER;
481       goto ErrorExit;
482     }
483     if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {
484       Status = EFI_INVALID_PARAMETER;
485       goto ErrorExit;
486     }
487 
488   } else {
489     //
490     // If RemainingDevicePath is the End of Device Path Node,
491     // skip enumerate any device and return EFI_SUCESSS
492     //
493     BeginningIdeChannel = IdeMaxChannel;
494     EndIdeChannel       = IdeMaxChannel - 1;
495     BeginningIdeDevice  = IdeMaxDevice;
496     EndIdeDevice        = IdeMaxDevice - 1;
497   }
498 
499   //
500   // Obtain IDE IO port registers' base addresses
501   //
502   Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
503   if (EFI_ERROR (Status)) {
504     goto ErrorExit;
505   }
506 
507   //
508   // Report status code: begin IdeBus initialization
509   //
510   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
511     EFI_PROGRESS_CODE,
512     (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
513     ParentDevicePath
514     );
515 
516   //
517   // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
518   //
519   for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
520 
521     IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
522 
523     //
524     // now obtain channel information fron IdeControllerInit protocol. Step9
525     //
526     Status = IdeInit->GetChannelInfo (
527                         IdeInit,
528                         IdeChannel,
529                         &ChannelEnabled,
530                         &MaxDevices
531                         );
532     if (EFI_ERROR (Status)) {
533       DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
534       continue;
535     }
536 
537     if (!ChannelEnabled) {
538       continue;
539     }
540 
541     EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);
542     ASSERT (EndIdeDevice < IdeMaxDevice);
543     //
544     // Now inform the IDE Controller Init Module. Sept10
545     //
546     IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
547 
548     //
549     // No reset channel function implemented. Sept11
550     //
551     IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
552 
553     //
554     // Step13
555     //
556     IdeInit->NotifyPhase (
557               IdeInit,
558               EfiIdeBusBeforeDevicePresenceDetection,
559               IdeChannel
560               );
561 
562     //
563     // Prepare to detect IDE device of this channel
564     //
565     InitializeIDEChannelData ();
566 
567     //
568     // -- 1st inner loop --- Master/Slave ------------  Step14
569     //
570     for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
571       //
572       // Check whether the configuration options allow this device
573       //
574       if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {
575         continue;
576       }
577 
578       //
579       // The device has been scanned in another Start(), No need to scan it again
580       // for perf optimization.
581       //
582       if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
583         continue;
584       }
585 
586       //
587       // create child handle for the detected device.
588       //
589       IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
590       if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
591         continue;
592       }
593 
594       IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
595 
596       ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
597 
598       IdeBlkIoDevicePtr->Signature  = IDE_BLK_IO_DEV_SIGNATURE;
599       IdeBlkIoDevicePtr->Channel    = (EFI_IDE_CHANNEL) IdeChannel;
600       IdeBlkIoDevicePtr->Device     = (EFI_IDE_DEVICE) IdeDevice;
601 
602       //
603       // initialize Block IO interface's Media pointer
604       //
605       IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
606 
607       //
608       // Initialize IDE IO port addresses, including Command Block registers
609       // and Control Block registers
610       //
611       IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
612       if (IdeBlkIoDevicePtr->IoPort == NULL) {
613         continue;
614       }
615 
616       ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
617       CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
618       ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
619 
620       IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
621       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
622       IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
623       IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
624       IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
625       IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
626       IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
627       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
628 
629       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
630       IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
631 
632       IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
633 
634       IdeBlkIoDevicePtr->PciIo = PciIo;
635       IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
636       IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
637 
638       //
639       // Report Status code: is about to detect IDE drive
640       //
641       REPORT_STATUS_CODE_EX (
642         EFI_PROGRESS_CODE,
643         (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
644         0,
645         &gEfiCallerIdGuid,
646         NULL,
647         NULL,
648         0
649       );
650 
651       //
652       // Discover device, now!
653       //
654       PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);
655       Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
656       PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);
657 
658       IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]  = TRUE;
659       IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]    = FALSE;
660 
661       if (!EFI_ERROR (Status)) {
662         //
663         // Set Device Path
664         //
665         ZeroMem (&NewNode, sizeof (NewNode));
666         NewNode.DevPath.Type    = MESSAGING_DEVICE_PATH;
667         NewNode.DevPath.SubType = MSG_ATAPI_DP;
668         SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
669 
670         NewNode.Atapi.PrimarySecondary  = (UINT8) IdeBlkIoDevicePtr->Channel;
671         NewNode.Atapi.SlaveMaster       = (UINT8) IdeBlkIoDevicePtr->Device;
672         NewNode.Atapi.Lun               = IdeBlkIoDevicePtr->Lun;
673         IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
674                                           ParentDevicePath,
675                                           &NewNode.DevPath
676                                           );
677         if (IdeBlkIoDevicePtr->DevicePath == NULL) {
678           ReleaseIdeResources (IdeBlkIoDevicePtr);
679           continue;
680         }
681 
682         //
683         // Submit identify data to IDE controller init driver
684         //
685         CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));
686         IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
687         IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
688       } else {
689         //
690         // Device detection failed
691         //
692         IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
693         IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
694         ReleaseIdeResources (IdeBlkIoDevicePtr);
695         IdeBlkIoDevicePtr = NULL;
696       }
697       //
698       // end of 1st inner loop ---
699       //
700     }
701     //
702     // end of 1st outer loop =========
703     //
704   }
705 
706   //
707   // = 2nd outer loop == Primary/Secondary =================
708   //
709   for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
710 
711     //
712     // -- 2nd inner loop --- Master/Slave --------
713     //
714     for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
715 
716       ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE);
717       if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
718         continue;
719       }
720 
721       if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
722         continue;
723       }
724 
725       Status = IdeInit->CalculateMode (
726                           IdeInit,
727                           IdeChannel,
728                           IdeDevice,
729                           &SupportedModes
730                           );
731       if (EFI_ERROR (Status)) {
732         DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
733         continue;
734       }
735 
736       ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice);
737       IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
738 
739       //
740       // Set best supported PIO mode on this IDE device
741       //
742       if (SupportedModes->PioMode.Mode <= AtaPioMode2) {
743         TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
744       } else {
745         TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
746       }
747 
748       TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
749 
750       if (SupportedModes->ExtModeCount == 0){
751         Status                  = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
752 
753         if (EFI_ERROR (Status)) {
754           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
755           ReleaseIdeResources (IdeBlkIoDevicePtr);
756           IdeBlkIoDevicePtr = NULL;
757           continue;
758         }
759       }
760 
761       //
762       // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
763       // be set together. Only one DMA mode can be set to a device. If setting
764       // DMA mode operation fails, we can continue moving on because we only use
765       // PIO mode at boot time. DMA modes are used by certain kind of OS booting
766       //
767       if (SupportedModes->UdmaMode.Valid) {
768 
769         TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
770         TransferMode.ModeNumber   = (UINT8) (SupportedModes->UdmaMode.Mode);
771         Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
772 
773         if (EFI_ERROR (Status)) {
774           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
775           ReleaseIdeResources (IdeBlkIoDevicePtr);
776           IdeBlkIoDevicePtr = NULL;
777           continue;
778         }
779         //
780         // Record Udma Mode
781         //
782         IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
783         IdeBlkIoDevicePtr->UdmaMode.Mode  = SupportedModes->UdmaMode.Mode;
784         EnableInterrupt (IdeBlkIoDevicePtr);
785       } else if (SupportedModes->MultiWordDmaMode.Valid) {
786 
787         TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
788         TransferMode.ModeNumber   = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
789         Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
790 
791         if (EFI_ERROR (Status)) {
792           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
793           ReleaseIdeResources (IdeBlkIoDevicePtr);
794           IdeBlkIoDevicePtr = NULL;
795           continue;
796         }
797 
798         EnableInterrupt (IdeBlkIoDevicePtr);
799       }
800       //
801       // Init driver parameters
802       //
803       DriveParameters.Sector          = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track;
804       DriveParameters.Heads           = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1);
805       DriveParameters.MultipleSector  = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;
806       //
807       // Set Parameters for the device:
808       // 1) Init
809       // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
810       //
811       if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
812         Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
813       }
814 
815       //
816       // Record PIO mode used in private data
817       //
818       IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
819 
820       //
821       // Set IDE controller Timing Blocks in the PCI Configuration Space
822       //
823       IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
824 
825       //
826       // Add Component Name for the IDE/ATAPI device that was discovered.
827       //
828       IdeBlkIoDevicePtr->ControllerNameTable = NULL;
829       ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);
830 
831       Status = gBS->InstallMultipleProtocolInterfaces (
832                       &IdeBlkIoDevicePtr->Handle,
833                       &gEfiDevicePathProtocolGuid,
834                       IdeBlkIoDevicePtr->DevicePath,
835                       &gEfiBlockIoProtocolGuid,
836                       &IdeBlkIoDevicePtr->BlkIo,
837                       &gEfiDiskInfoProtocolGuid,
838                       &IdeBlkIoDevicePtr->DiskInfo,
839                       NULL
840                       );
841 
842       if (EFI_ERROR (Status)) {
843         ReleaseIdeResources (IdeBlkIoDevicePtr);
844       }
845 
846       gBS->OpenProtocol (
847             Controller,
848             &gEfiPciIoProtocolGuid,
849             (VOID **) &PciIo,
850             This->DriverBindingHandle,
851             IdeBlkIoDevicePtr->Handle,
852             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
853             );
854 
855       IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
856 
857       //
858       // Report status code: device eanbled!
859       //
860       REPORT_STATUS_CODE_WITH_DEVICE_PATH (
861         EFI_PROGRESS_CODE,
862         (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
863         IdeBlkIoDevicePtr->DevicePath
864         );
865 
866       //
867       // Create event to clear pending IDE interrupt
868       //
869       Status = gBS->CreateEventEx (
870                       EVT_NOTIFY_SIGNAL,
871                       TPL_NOTIFY,
872                       ClearInterrupt,
873                       IdeBlkIoDevicePtr,
874                       &gEfiEventExitBootServicesGuid,
875                       &IdeBlkIoDevicePtr->ExitBootServiceEvent
876                       );
877 
878       //
879       // end of 2nd inner loop ----
880       //
881     }
882     //
883     // end of 2nd outer loop ==========
884     //
885   }
886 
887   //
888   // All configurations done! Notify IdeController to do post initialization
889   // work such as saving IDE controller PCI settings for S3 resume
890   //
891   IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
892 
893   if (SupportedModes != NULL) {
894     FreePool (SupportedModes);
895   }
896 
897   PERF_START (NULL, "Finish IDE detection", "IDE", 1);
898   PERF_END (NULL, "Finish IDE detection", "IDE", 0);
899 
900   return EFI_SUCCESS;
901 
902 ErrorExit:
903 
904   //
905   // Report error code: controller error
906   //
907   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
908     EFI_ERROR_CODE | EFI_ERROR_MINOR,
909     (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
910     ParentDevicePath
911     );
912 
913   gBS->CloseProtocol (
914         Controller,
915         &gEfiIdeControllerInitProtocolGuid,
916         This->DriverBindingHandle,
917         Controller
918         );
919 
920   gBS->UninstallMultipleProtocolInterfaces (
921         Controller,
922         &gEfiCallerIdGuid,
923         IdeBusDriverPrivateData,
924         NULL
925         );
926 
927   if (IdeBusDriverPrivateData != NULL) {
928     gBS->FreePool (IdeBusDriverPrivateData);
929   }
930 
931   if (SupportedModes != NULL) {
932     gBS->FreePool (SupportedModes);
933   }
934 
935   gBS->CloseProtocol (
936         Controller,
937         &gEfiPciIoProtocolGuid,
938         This->DriverBindingHandle,
939         Controller
940         );
941 
942   gBS->CloseProtocol (
943         Controller,
944         &gEfiDevicePathProtocolGuid,
945         This->DriverBindingHandle,
946         Controller
947         );
948 
949   return Status;
950 
951 }
952 /**
953   Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
954   child handle attached to the controller handle if there are.
955 
956   @param  This Protocol instance pointer.
957   @param  Controller Handle of device to stop driver on
958   @param  NumberOfChildren Not used
959   @param  ChildHandleBuffer Not used
960 
961   @retval  EFI_SUCCESS This driver is removed DeviceHandle
962   @retval  other This driver was not removed from this device
963 
964 **/
965 EFI_STATUS
966 EFIAPI
IDEBusDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)967 IDEBusDriverBindingStop (
968   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
969   IN  EFI_HANDLE                      Controller,
970   IN  UINTN                           NumberOfChildren,
971   IN  EFI_HANDLE                      *ChildHandleBuffer
972   )
973 {
974   EFI_STATUS                  Status;
975   EFI_PCI_IO_PROTOCOL         *PciIo;
976   BOOLEAN                     AllChildrenStopped;
977   UINTN                       Index;
978   IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
979   UINT64                      Supports;
980 
981   IdeBusDriverPrivateData = NULL;
982 
983   if (NumberOfChildren == 0) {
984 
985     Status = gBS->OpenProtocol (
986                     Controller,
987                     &gEfiPciIoProtocolGuid,
988                     (VOID **) &PciIo,
989                     This->DriverBindingHandle,
990                     Controller,
991                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
992                     );
993     if (!EFI_ERROR (Status)) {
994       Status = PciIo->Attributes (
995                         PciIo,
996                         EfiPciIoAttributeOperationSupported,
997                         0,
998                         &Supports
999                         );
1000       if (!EFI_ERROR (Status)) {
1001         Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE);
1002         PciIo->Attributes (
1003                 PciIo,
1004                 EfiPciIoAttributeOperationDisable,
1005                 Supports,
1006                 NULL
1007                 );
1008       }
1009     }
1010 
1011     gBS->OpenProtocol (
1012           Controller,
1013           &gEfiCallerIdGuid,
1014           (VOID **) &IdeBusDriverPrivateData,
1015           This->DriverBindingHandle,
1016           Controller,
1017           EFI_OPEN_PROTOCOL_GET_PROTOCOL
1018           );
1019 
1020     gBS->UninstallMultipleProtocolInterfaces (
1021           Controller,
1022           &gEfiCallerIdGuid,
1023           IdeBusDriverPrivateData,
1024           NULL
1025           );
1026 
1027     if (IdeBusDriverPrivateData != NULL) {
1028       gBS->FreePool (IdeBusDriverPrivateData);
1029     }
1030     //
1031     // Close the bus driver
1032     //
1033     gBS->CloseProtocol (
1034           Controller,
1035           &gEfiIdeControllerInitProtocolGuid,
1036           This->DriverBindingHandle,
1037           Controller
1038           );
1039     gBS->CloseProtocol (
1040           Controller,
1041           &gEfiPciIoProtocolGuid,
1042           This->DriverBindingHandle,
1043           Controller
1044           );
1045     gBS->CloseProtocol (
1046           Controller,
1047           &gEfiDevicePathProtocolGuid,
1048           This->DriverBindingHandle,
1049           Controller
1050           );
1051 
1052     return EFI_SUCCESS;
1053   }
1054 
1055   AllChildrenStopped = TRUE;
1056 
1057   for (Index = 0; Index < NumberOfChildren; Index++) {
1058 
1059     Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
1060 
1061     if (EFI_ERROR (Status)) {
1062       AllChildrenStopped = FALSE;
1063     }
1064   }
1065 
1066   if (!AllChildrenStopped) {
1067     return EFI_DEVICE_ERROR;
1068   }
1069 
1070   return EFI_SUCCESS;
1071 }
1072 
1073 /**
1074   issue ATA or ATAPI command to reset a block IO device.
1075   @param  This                  Block IO protocol instance pointer.
1076   @param  ExtendedVerification  If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
1077                                 If TRUE, for ATAPI device, driver need invoke ATA reset method after
1078                                 invoke ATAPI reset method
1079 
1080   @retval EFI_DEVICE_ERROR      When the device is neighther ATA device or ATAPI device.
1081   @retval EFI_SUCCESS           The device reset successfully
1082 
1083 **/
1084 EFI_STATUS
1085 EFIAPI
IDEBlkIoReset(IN EFI_BLOCK_IO_PROTOCOL * This,IN BOOLEAN ExtendedVerification)1086 IDEBlkIoReset (
1087   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1088   IN  BOOLEAN                 ExtendedVerification
1089   )
1090 {
1091   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1092   EFI_STATUS      Status;
1093   EFI_TPL         OldTpl;
1094 
1095   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1096 
1097   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1098   //
1099   // Requery IDE IO resources in case of the switch of native and legacy modes
1100   //
1101   ReassignIdeResources (IdeBlkIoDevice);
1102 
1103   //
1104   // for ATA device, using ATA reset method
1105   //
1106   if (IdeBlkIoDevice->Type == IdeHardDisk ||
1107       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1108     Status = AtaSoftReset (IdeBlkIoDevice);
1109     goto Done;
1110   }
1111 
1112   if (IdeBlkIoDevice->Type == IdeUnknown) {
1113     Status = EFI_DEVICE_ERROR;
1114     goto Done;
1115   }
1116 
1117   //
1118   // for ATAPI device, using ATAPI reset method
1119   //
1120   Status = AtapiSoftReset (IdeBlkIoDevice);
1121   if (ExtendedVerification) {
1122     Status = AtaSoftReset (IdeBlkIoDevice);
1123   }
1124 
1125 Done:
1126   gBS->RestoreTPL (OldTpl);
1127   return Status;
1128 }
1129 
1130 /**
1131   Read data from a block IO device
1132 
1133   @param  This       Block IO protocol instance pointer.
1134   @param  MediaId    The media ID of the device
1135   @param  Lba        Starting LBA address to read data
1136   @param  BufferSize The size of data to be read
1137   @param  Buffer     Caller supplied buffer to save data
1138 
1139   @retval EFI_DEVICE_ERROR  unknown device type
1140   @retval other             read data status.
1141 
1142 **/
1143 EFI_STATUS
1144 EFIAPI
IDEBlkIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,OUT VOID * Buffer)1145 IDEBlkIoReadBlocks (
1146   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1147   IN  UINT32                  MediaId,
1148   IN  EFI_LBA                 Lba,
1149   IN  UINTN                   BufferSize,
1150   OUT VOID                    *Buffer
1151   )
1152 {
1153   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1154   EFI_STATUS      Status;
1155   EFI_TPL         OldTpl;
1156 
1157   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1158 
1159   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1160 
1161   //
1162   // Requery IDE IO resources in case of the switch of native and legacy modes
1163   //
1164   ReassignIdeResources (IdeBlkIoDevice);
1165 
1166   //
1167   // For ATA compatible device, use ATA read block's mechanism
1168   //
1169   if (IdeBlkIoDevice->Type == IdeHardDisk ||
1170       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1171     Status = AtaBlkIoReadBlocks (
1172             IdeBlkIoDevice,
1173             MediaId,
1174             Lba,
1175             BufferSize,
1176             Buffer
1177             );
1178     goto Done;
1179   }
1180 
1181   if (IdeBlkIoDevice->Type == IdeUnknown) {
1182     Status = EFI_DEVICE_ERROR;
1183     goto Done;
1184   }
1185 
1186   //
1187   // for ATAPI device, using ATAPI read block's mechanism
1188   //
1189   Status = AtapiBlkIoReadBlocks (
1190           IdeBlkIoDevice,
1191           MediaId,
1192           Lba,
1193           BufferSize,
1194           Buffer
1195           );
1196 
1197 Done:
1198   gBS->RestoreTPL (OldTpl);
1199 
1200   return Status;
1201 }
1202 
1203 /**
1204   Write data to block io device.
1205 
1206   @param  This       Protocol instance pointer.
1207   @param  MediaId    The media ID of the device
1208   @param  Lba        Starting LBA address to write data
1209   @param  BufferSize The size of data to be written
1210   @param  Buffer     Caller supplied buffer to save data
1211 
1212   @retval EFI_DEVICE_ERROR  unknown device type
1213   @retval other             write data status
1214 
1215 **/
1216 EFI_STATUS
1217 EFIAPI
IDEBlkIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL * This,IN UINT32 MediaId,IN EFI_LBA Lba,IN UINTN BufferSize,IN VOID * Buffer)1218 IDEBlkIoWriteBlocks (
1219   IN  EFI_BLOCK_IO_PROTOCOL   *This,
1220   IN  UINT32                  MediaId,
1221   IN  EFI_LBA                 Lba,
1222   IN  UINTN                   BufferSize,
1223   IN  VOID                    *Buffer
1224   )
1225 {
1226   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1227   EFI_STATUS      Status;
1228   EFI_TPL         OldTpl;
1229 
1230   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1231 
1232   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
1233   //
1234   // Requery IDE IO resources in case of the switch of native and legacy modes
1235   //
1236   ReassignIdeResources (IdeBlkIoDevice);
1237 
1238   //
1239   // for ATA device, using ATA write block's mechanism
1240   //
1241   if (IdeBlkIoDevice->Type == IdeHardDisk ||
1242       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
1243 
1244     Status = AtaBlkIoWriteBlocks (
1245             IdeBlkIoDevice,
1246             MediaId,
1247             Lba,
1248             BufferSize,
1249             Buffer
1250             );
1251     goto Done;
1252   }
1253 
1254   if (IdeBlkIoDevice->Type == IdeUnknown) {
1255     Status = EFI_DEVICE_ERROR;
1256     goto Done;
1257   }
1258 
1259   //
1260   // for ATAPI device, using ATAPI write block's mechanism
1261   //
1262   Status = AtapiBlkIoWriteBlocks (
1263           IdeBlkIoDevice,
1264           MediaId,
1265           Lba,
1266           BufferSize,
1267           Buffer
1268           );
1269 
1270 Done:
1271   gBS->RestoreTPL (OldTpl);
1272   return Status;
1273 }
1274 /**
1275   Flushes all modified data to a physical block devices
1276 
1277   @param  This  Indicates a pointer to the calling context which to sepcify a
1278                 sepcific block device
1279 
1280   @retval EFI_SUCCESS   Always return success.
1281 **/
1282 EFI_STATUS
1283 EFIAPI
IDEBlkIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL * This)1284 IDEBlkIoFlushBlocks (
1285   IN  EFI_BLOCK_IO_PROTOCOL   *This
1286   )
1287 {
1288   //
1289   // return directly
1290   //
1291   return EFI_SUCCESS;
1292 }
1293 
1294 /**
1295   This function is used by the IDE bus driver to get inquiry data.
1296   Data format of Identify data is defined by the Interface GUID.
1297 
1298   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1299   @param  InquiryData           Pointer to a buffer for the inquiry data.
1300   @param  InquiryDataSize       Pointer to the value for the inquiry data size.
1301 
1302   @retval EFI_SUCCESS           The command was accepted without any errors.
1303   @retval EFI_NOT_FOUND         Device does not support this data class
1304   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device
1305   @retval EFI_BUFFER_TOO_SMALL  IntquiryDataSize not big enough
1306 
1307 **/
1308 EFI_STATUS
1309 EFIAPI
IDEDiskInfoInquiry(IN EFI_DISK_INFO_PROTOCOL * This,IN OUT VOID * InquiryData,IN OUT UINT32 * InquiryDataSize)1310 IDEDiskInfoInquiry (
1311   IN     EFI_DISK_INFO_PROTOCOL   *This,
1312   IN OUT VOID                     *InquiryData,
1313   IN OUT UINT32                   *InquiryDataSize
1314   )
1315 {
1316   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1317 
1318   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1319 
1320   if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {
1321     *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
1322     return EFI_BUFFER_TOO_SMALL;
1323   }
1324 
1325   if (IdeBlkIoDevice->InquiryData == NULL) {
1326     return EFI_NOT_FOUND;
1327   }
1328 
1329   gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));
1330   *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
1331 
1332   return EFI_SUCCESS;
1333 }
1334 
1335 /**
1336   This function is used by the IDE bus driver to get identify data.
1337   Data format of Identify data is defined by the Interface GUID.
1338 
1339   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1340   @param  IdentifyData          Pointer to a buffer for the identify data.
1341   @param  IdentifyDataSize      Pointer to the value for the identify data size.
1342 
1343   @retval EFI_SUCCESS           The command was accepted without any errors.
1344   @retval EFI_NOT_FOUND         Device does not support this data class
1345   @retval EFI_DEVICE_ERROR      Error reading IdentifyData from device
1346   @retval EFI_BUFFER_TOO_SMALL  IdentifyDataSize not big enough
1347 
1348 **/
1349 EFI_STATUS
1350 EFIAPI
IDEDiskInfoIdentify(IN EFI_DISK_INFO_PROTOCOL * This,IN OUT VOID * IdentifyData,IN OUT UINT32 * IdentifyDataSize)1351 IDEDiskInfoIdentify (
1352   IN     EFI_DISK_INFO_PROTOCOL   *This,
1353   IN OUT VOID                     *IdentifyData,
1354   IN OUT UINT32                   *IdentifyDataSize
1355   )
1356 {
1357   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1358 
1359   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1360 
1361   if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
1362     *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
1363     return EFI_BUFFER_TOO_SMALL;
1364   }
1365 
1366   if (IdeBlkIoDevice->IdData == NULL) {
1367     return EFI_NOT_FOUND;
1368   }
1369 
1370   gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));
1371   *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
1372 
1373   return EFI_SUCCESS;
1374 }
1375 
1376 /**
1377   This function is used by the IDE bus driver to get sense data.
1378   Data format of Sense data is defined by the Interface GUID.
1379 
1380   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1381   @param  SenseData             Pointer to the SenseData.
1382   @param  SenseDataSize         Size of SenseData in bytes.
1383   @param  SenseDataNumber       Pointer to the value for the identify data size.
1384 
1385   @retval EFI_SUCCESS           The command was accepted without any errors.
1386   @retval EFI_NOT_FOUND         Device does not support this data class
1387   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device
1388   @retval EFI_BUFFER_TOO_SMALL  SenseDataSize not big enough
1389 
1390 **/
1391 EFI_STATUS
1392 EFIAPI
IDEDiskInfoSenseData(IN EFI_DISK_INFO_PROTOCOL * This,IN OUT VOID * SenseData,IN OUT UINT32 * SenseDataSize,OUT UINT8 * SenseDataNumber)1393 IDEDiskInfoSenseData (
1394   IN     EFI_DISK_INFO_PROTOCOL   *This,
1395   IN OUT VOID                     *SenseData,
1396   IN OUT UINT32                   *SenseDataSize,
1397   OUT    UINT8                    *SenseDataNumber
1398   )
1399 {
1400   return EFI_NOT_FOUND;
1401 }
1402 
1403 /**
1404   This function is used by the IDE bus driver to get controller information.
1405 
1406   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
1407   @param  IdeChannel            Pointer to the Ide Channel number. Primary or secondary.
1408   @param  IdeDevice             Pointer to the Ide Device number. Master or slave.
1409 
1410   @retval EFI_SUCCESS           IdeChannel and IdeDevice are valid
1411   @retval EFI_UNSUPPORTED       This is not an IDE device
1412 
1413 **/
1414 EFI_STATUS
1415 EFIAPI
IDEDiskInfoWhichIde(IN EFI_DISK_INFO_PROTOCOL * This,OUT UINT32 * IdeChannel,OUT UINT32 * IdeDevice)1416 IDEDiskInfoWhichIde (
1417   IN  EFI_DISK_INFO_PROTOCOL   *This,
1418   OUT UINT32                   *IdeChannel,
1419   OUT UINT32                   *IdeDevice
1420   )
1421 {
1422   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
1423 
1424   IdeBlkIoDevice  = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
1425   *IdeChannel     = IdeBlkIoDevice->Channel;
1426   *IdeDevice      = IdeBlkIoDevice->Device;
1427 
1428   return EFI_SUCCESS;
1429 }
1430 
1431 /**
1432   The is an event(generally the event is exitBootService event) call back function.
1433   Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1434 
1435   @param  Event   Pointer to this event
1436   @param  Context Event handler private data
1437 
1438 **/
1439 VOID
1440 EFIAPI
ClearInterrupt(IN EFI_EVENT Event,IN VOID * Context)1441 ClearInterrupt (
1442   IN EFI_EVENT  Event,
1443   IN VOID       *Context
1444   )
1445 {
1446   EFI_STATUS      Status;
1447   UINT64          IoPortForBmis;
1448   UINT8           RegisterValue;
1449   IDE_BLK_IO_DEV  *IdeDev;
1450 
1451   //
1452   // Get our context
1453   //
1454   IdeDev = (IDE_BLK_IO_DEV *) Context;
1455 
1456   //
1457   // Obtain IDE IO port registers' base addresses
1458   //
1459   Status = ReassignIdeResources (IdeDev);
1460   if (EFI_ERROR (Status)) {
1461     return;
1462   }
1463 
1464   //
1465   // Check whether interrupt is pending
1466   //
1467 
1468   //
1469   // Reset IDE device to force it de-assert interrupt pin
1470   // Note: this will reset all devices on this IDE channel
1471   //
1472   Status = AtaSoftReset (IdeDev);
1473   if (EFI_ERROR (Status)) {
1474     return;
1475   }
1476 
1477   //
1478   // Get base address of IDE Bus Master Status Regsiter
1479   //
1480   if (IdePrimary == IdeDev->Channel) {
1481     IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
1482   } else {
1483     if (IdeSecondary == IdeDev->Channel) {
1484       IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
1485     } else {
1486       return;
1487     }
1488   }
1489   //
1490   // Read BMIS register and clear ERROR and INTR bit
1491   //
1492   IdeDev->PciIo->Io.Read (
1493                       IdeDev->PciIo,
1494                       EfiPciIoWidthUint8,
1495                       EFI_PCI_IO_PASS_THROUGH_BAR,
1496                       IoPortForBmis,
1497                       1,
1498                       &RegisterValue
1499                       );
1500 
1501   RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
1502 
1503   IdeDev->PciIo->Io.Write (
1504                       IdeDev->PciIo,
1505                       EfiPciIoWidthUint8,
1506                       EFI_PCI_IO_PASS_THROUGH_BAR,
1507                       IoPortForBmis,
1508                       1,
1509                       &RegisterValue
1510                       );
1511 
1512   //
1513   // Select the other device on this channel to ensure this device to release the interrupt pin
1514   //
1515   if (IdeDev->Device == 0) {
1516     RegisterValue = (1 << 4) | 0xe0;
1517   } else {
1518     RegisterValue = (0 << 4) | 0xe0;
1519   }
1520   IDEWritePortB (
1521     IdeDev->PciIo,
1522     IdeDev->IoPort->Head,
1523     RegisterValue
1524     );
1525 
1526 }
1527 
1528 /**
1529   The user Entry Point for module IdeBus. The user code starts with this function.
1530 
1531   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
1532   @param[in] SystemTable    A pointer to the EFI System Table.
1533 
1534   @retval EFI_SUCCESS       The entry point is executed successfully.
1535   @retval other             Some error occurs when executing this entry point.
1536 
1537 **/
1538 EFI_STATUS
1539 EFIAPI
InitializeIdeBus(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1540 InitializeIdeBus(
1541   IN EFI_HANDLE           ImageHandle,
1542   IN EFI_SYSTEM_TABLE     *SystemTable
1543   )
1544 {
1545   EFI_STATUS              Status;
1546 
1547   //
1548   // Install driver model protocol(s).
1549   //
1550   Status = EfiLibInstallAllDriverProtocols2 (
1551              ImageHandle,
1552              SystemTable,
1553              &gIDEBusDriverBinding,
1554              ImageHandle,
1555              &gIDEBusComponentName,
1556              &gIDEBusComponentName2,
1557              NULL,
1558              NULL,
1559              &gIDEBusDriverDiagnostics,
1560              &gIDEBusDriverDiagnostics2
1561              );
1562   ASSERT_EFI_ERROR (Status);
1563 
1564   return Status;
1565 }
1566