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