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