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